diff options
Diffstat (limited to 'src/core')
36 files changed, 1166 insertions, 869 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index ebedcb710..5caaee474 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -30,6 +30,7 @@ set(SRCS hle/kernel/kernel.cpp hle/kernel/mutex.cpp hle/kernel/process.cpp + hle/kernel/resource_limit.cpp hle/kernel/semaphore.cpp hle/kernel/session.cpp hle/kernel/shared_memory.cpp @@ -99,7 +100,7 @@ set(SRCS loader/loader.cpp loader/ncch.cpp mem_map.cpp - mem_map_funcs.cpp + memory.cpp settings.cpp system.cpp ) @@ -141,6 +142,7 @@ set(HEADERS hle/kernel/kernel.h hle/kernel/mutex.h hle/kernel/process.h + hle/kernel/resource_limit.h hle/kernel/semaphore.h hle/kernel/session.h hle/kernel/shared_memory.h @@ -211,6 +213,8 @@ set(HEADERS loader/loader.h loader/ncch.h mem_map.h + memory.h + memory_setup.h settings.h system.h ) diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index cb45cfb38..66282a7e6 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -10,9 +10,10 @@ #include "common/logging/log.h" #include "common/profiler.h" -#include "core/mem_map.h" +#include "core/memory.h" #include "core/hle/svc.h" #include "core/arm/disassembler/arm_disasm.h" +#include "core/arm/dyncom/arm_dyncom_dec.h" #include "core/arm/dyncom/arm_dyncom_interpreter.h" #include "core/arm/dyncom/arm_dyncom_thumb.h" #include "core/arm/dyncom/arm_dyncom_run.h" @@ -68,6 +69,67 @@ static void remove_exclusive(ARMul_State* state, ARMword addr){ state->exclusive_tag = 0xFFFFFFFF; } +static int CondPassed(ARMul_State* cpu, unsigned int cond) { + const u32 NFLAG = cpu->NFlag; + const u32 ZFLAG = cpu->ZFlag; + const u32 CFLAG = cpu->CFlag; + const u32 VFLAG = cpu->VFlag; + + int temp = 0; + + switch (cond) { + case 0x0: + temp = ZFLAG; + break; + case 0x1: // NE + temp = !ZFLAG; + break; + case 0x2: // CS + temp = CFLAG; + break; + case 0x3: // CC + temp = !CFLAG; + break; + case 0x4: // MI + temp = NFLAG; + break; + case 0x5: // PL + temp = !NFLAG; + break; + case 0x6: // VS + temp = VFLAG; + break; + case 0x7: // VC + temp = !VFLAG; + break; + case 0x8: // HI + temp = (CFLAG && !ZFLAG); + break; + case 0x9: // LS + temp = (!CFLAG || ZFLAG); + break; + case 0xa: // GE + temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG)); + break; + case 0xb: // LT + temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)); + break; + case 0xc: // GT + temp = ((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG)); + break; + case 0xd: // LE + temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG; + break; + case 0xe: // AL + temp = 1; + break; + case 0xf: + temp = 1; + break; + } + return temp; +} + static unsigned int DPO(Immediate)(ARMul_State* cpu, unsigned int sht_oper) { unsigned int immed_8 = BITS(sht_oper, 0, 7); unsigned int rotate_imm = BITS(sht_oper, 8, 11); @@ -224,14 +286,12 @@ static unsigned int DPO(RotateRightByRegister)(ARMul_State* cpu, unsigned int sh typedef void (*get_addr_fp_t)(ARMul_State *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int rw); -typedef struct _ldst_inst { +struct ldst_inst { unsigned int inst; get_addr_fp_t get_addr; -} ldst_inst; +}; #define DEBUG_MSG LOG_DEBUG(Core_ARM11, "inst is %x", inst); CITRA_IGNORE_EXIT(0) -int CondPassed(ARMul_State* cpu, unsigned int cond); - #define LnSWoUB(s) glue(LnSWoUB, s) #define MLnS(s) glue(MLnS, s) #define LdnStM(s) glue(LdnStM, s) @@ -647,255 +707,248 @@ static void LnSWoUB(ScaledRegisterOffset)(ARMul_State* cpu, unsigned int inst, u virt_addr = addr; } -typedef struct _arm_inst { +struct arm_inst { unsigned int idx; unsigned int cond; int br; int load_r15; char component[0]; -} arm_inst; +}; -typedef struct generic_arm_inst { +struct generic_arm_inst { u32 Ra; u32 Rm; u32 Rn; u32 Rd; u8 op1; u8 op2; -} generic_arm_inst; +}; -typedef struct _adc_inst { +struct adc_inst { unsigned int I; unsigned int S; unsigned int Rn; unsigned int Rd; unsigned int shifter_operand; shtop_fp_t shtop_func; -} adc_inst; +}; -typedef struct _add_inst { +struct add_inst { unsigned int I; unsigned int S; unsigned int Rn; unsigned int Rd; unsigned int shifter_operand; shtop_fp_t shtop_func; -} add_inst; +}; -typedef struct _orr_inst { +struct orr_inst { unsigned int I; unsigned int S; unsigned int Rn; unsigned int Rd; unsigned int shifter_operand; shtop_fp_t shtop_func; -} orr_inst; +}; -typedef struct _and_inst { +struct and_inst { unsigned int I; unsigned int S; unsigned int Rn; unsigned int Rd; unsigned int shifter_operand; shtop_fp_t shtop_func; -} and_inst; +}; -typedef struct _eor_inst { +struct eor_inst { unsigned int I; unsigned int S; unsigned int Rn; unsigned int Rd; unsigned int shifter_operand; shtop_fp_t shtop_func; -} eor_inst; +}; -typedef struct _bbl_inst { +struct bbl_inst { unsigned int L; int signed_immed_24; unsigned int next_addr; unsigned int jmp_addr; -} bbl_inst; +}; -typedef struct _bx_inst { +struct bx_inst { unsigned int Rm; -} bx_inst; +}; -typedef struct _blx_inst { +struct blx_inst { union { int32_t signed_immed_24; uint32_t Rm; } val; unsigned int inst; -} blx_inst; +}; -typedef struct _clz_inst { +struct clz_inst { unsigned int Rm; unsigned int Rd; -} clz_inst; +}; -typedef struct _cps_inst { +struct cps_inst { unsigned int imod0; unsigned int imod1; unsigned int mmod; unsigned int A, I, F; unsigned int mode; -} cps_inst; +}; -typedef struct _clrex_inst { -} clrex_inst; +struct clrex_inst { +}; -typedef struct _cpy_inst { +struct cpy_inst { unsigned int Rm; unsigned int Rd; -} cpy_inst; +}; -typedef struct _bic_inst { +struct bic_inst { unsigned int I; unsigned int S; unsigned int Rn; unsigned int Rd; unsigned int shifter_operand; shtop_fp_t shtop_func; -} bic_inst; +}; -typedef struct _sub_inst { +struct sub_inst { unsigned int I; unsigned int S; unsigned int Rn; unsigned int Rd; unsigned int shifter_operand; shtop_fp_t shtop_func; -} sub_inst; +}; -typedef struct _tst_inst { +struct tst_inst { unsigned int I; unsigned int S; unsigned int Rn; unsigned int Rd; unsigned int shifter_operand; shtop_fp_t shtop_func; -} tst_inst; +}; -typedef struct _cmn_inst { +struct cmn_inst { unsigned int I; unsigned int Rn; unsigned int shifter_operand; shtop_fp_t shtop_func; -} cmn_inst; +}; -typedef struct _teq_inst { +struct teq_inst { unsigned int I; unsigned int Rn; unsigned int shifter_operand; shtop_fp_t shtop_func; -} teq_inst; +}; -typedef struct _stm_inst { +struct stm_inst { unsigned int inst; -} stm_inst; +}; struct bkpt_inst { u32 imm; }; -struct blx1_inst { - unsigned int addr; +struct stc_inst { }; -struct blx2_inst { - unsigned int Rm; +struct ldc_inst { }; -typedef struct _stc_inst { -} stc_inst; - -typedef struct _ldc_inst { -} ldc_inst; - -typedef struct _swi_inst { +struct swi_inst { unsigned int num; -} swi_inst; +}; -typedef struct _cmp_inst { +struct cmp_inst { unsigned int I; unsigned int Rn; unsigned int shifter_operand; shtop_fp_t shtop_func; -} cmp_inst; +}; -typedef struct _mov_inst { +struct mov_inst { unsigned int I; unsigned int S; unsigned int Rd; unsigned int shifter_operand; shtop_fp_t shtop_func; -} mov_inst; +}; -typedef struct _mvn_inst { +struct mvn_inst { unsigned int I; unsigned int S; unsigned int Rd; unsigned int shifter_operand; shtop_fp_t shtop_func; -} mvn_inst; +}; -typedef struct _rev_inst { +struct rev_inst { unsigned int Rd; unsigned int Rm; unsigned int op1; unsigned int op2; -} rev_inst; +}; -typedef struct _rsb_inst { +struct rsb_inst { unsigned int I; unsigned int S; unsigned int Rn; unsigned int Rd; unsigned int shifter_operand; shtop_fp_t shtop_func; -} rsb_inst; +}; -typedef struct _rsc_inst { +struct rsc_inst { unsigned int I; unsigned int S; unsigned int Rn; unsigned int Rd; unsigned int shifter_operand; shtop_fp_t shtop_func; -} rsc_inst; +}; -typedef struct _sbc_inst { +struct sbc_inst { unsigned int I; unsigned int S; unsigned int Rn; unsigned int Rd; unsigned int shifter_operand; shtop_fp_t shtop_func; -} sbc_inst; +}; -typedef struct _mul_inst { +struct mul_inst { unsigned int S; unsigned int Rd; unsigned int Rs; unsigned int Rm; -} mul_inst; +}; -typedef struct _smul_inst { +struct smul_inst { unsigned int Rd; unsigned int Rs; unsigned int Rm; unsigned int x; unsigned int y; -} smul_inst; +}; -typedef struct _umull_inst { +struct umull_inst { unsigned int S; unsigned int RdHi; unsigned int RdLo; unsigned int Rs; unsigned int Rm; -} umull_inst; -typedef struct _smlad_inst { +}; + +struct smlad_inst { unsigned int m; unsigned int Rm; unsigned int Rd; @@ -903,58 +956,58 @@ typedef struct _smlad_inst { unsigned int Rn; unsigned int op1; unsigned int op2; -} smlad_inst; +}; -typedef struct _smla_inst { +struct smla_inst { unsigned int x; unsigned int y; unsigned int Rm; unsigned int Rd; unsigned int Rs; unsigned int Rn; -} smla_inst; +}; -typedef struct smlalxy_inst { +struct smlalxy_inst { unsigned int x; unsigned int y; unsigned int RdLo; unsigned int RdHi; unsigned int Rm; unsigned int Rn; -} smlalxy_inst; +}; -typedef struct ssat_inst { +struct ssat_inst { unsigned int Rn; unsigned int Rd; unsigned int imm5; unsigned int sat_imm; unsigned int shift_type; -} ssat_inst; +}; -typedef struct umaal_inst { +struct umaal_inst { unsigned int Rn; unsigned int Rm; unsigned int RdHi; unsigned int RdLo; -} umaal_inst; +}; -typedef struct _umlal_inst { +struct umlal_inst { unsigned int S; unsigned int Rm; unsigned int Rs; unsigned int RdHi; unsigned int RdLo; -} umlal_inst; +}; -typedef struct _smlal_inst { +struct smlal_inst { unsigned int S; unsigned int Rm; unsigned int Rs; unsigned int RdHi; unsigned int RdLo; -} smlal_inst; +}; -typedef struct smlald_inst { +struct smlald_inst { unsigned int RdLo; unsigned int RdHi; unsigned int Rm; @@ -962,17 +1015,17 @@ typedef struct smlald_inst { unsigned int swap; unsigned int op1; unsigned int op2; -} smlald_inst; +}; -typedef struct _mla_inst { +struct mla_inst { unsigned int S; unsigned int Rn; unsigned int Rd; unsigned int Rs; unsigned int Rm; -} mla_inst; +}; -typedef struct _mrc_inst { +struct mrc_inst { unsigned int opcode_1; unsigned int opcode_2; unsigned int cp_num; @@ -980,9 +1033,9 @@ typedef struct _mrc_inst { unsigned int crm; unsigned int Rd; unsigned int inst; -} mrc_inst; +}; -typedef struct _mcr_inst { +struct mcr_inst { unsigned int opcode_1; unsigned int opcode_2; unsigned int cp_num; @@ -990,77 +1043,77 @@ typedef struct _mcr_inst { unsigned int crm; unsigned int Rd; unsigned int inst; -} mcr_inst; +}; -typedef struct mcrr_inst { +struct mcrr_inst { unsigned int opcode_1; unsigned int cp_num; unsigned int crm; unsigned int rt; unsigned int rt2; -} mcrr_inst; +}; -typedef struct _mrs_inst { +struct mrs_inst { unsigned int R; unsigned int Rd; -} mrs_inst; +}; -typedef struct _msr_inst { +struct msr_inst { unsigned int field_mask; unsigned int R; unsigned int inst; -} msr_inst; +}; -typedef struct _pld_inst { -} pld_inst; +struct pld_inst { +}; -typedef struct _sxtb_inst { +struct sxtb_inst { unsigned int Rd; unsigned int Rm; unsigned int rotate; -} sxtb_inst; +}; -typedef struct _sxtab_inst { +struct sxtab_inst { unsigned int Rd; unsigned int Rn; unsigned int Rm; unsigned rotate; -} sxtab_inst; +}; -typedef struct _sxtah_inst { +struct sxtah_inst { unsigned int Rd; unsigned int Rn; unsigned int Rm; unsigned int rotate; -} sxtah_inst; +}; -typedef struct _sxth_inst { +struct sxth_inst { unsigned int Rd; unsigned int Rm; unsigned int rotate; -} sxth_inst; +}; -typedef struct _uxtab_inst { +struct uxtab_inst { unsigned int Rn; unsigned int Rd; unsigned int rotate; unsigned int Rm; -} uxtab_inst; +}; -typedef struct _uxtah_inst { +struct uxtah_inst { unsigned int Rn; unsigned int Rd; unsigned int rotate; unsigned int Rm; -} uxtah_inst; +}; -typedef struct _uxth_inst { +struct uxth_inst { unsigned int Rd; unsigned int Rm; unsigned int rotate; -} uxth_inst; +}; -typedef struct _cdp_inst { +struct cdp_inst { unsigned int opcode_1; unsigned int CRn; unsigned int CRd; @@ -1068,56 +1121,56 @@ typedef struct _cdp_inst { unsigned int opcode_2; unsigned int CRm; unsigned int inst; -}cdp_inst; +}; -typedef struct _uxtb_inst { +struct uxtb_inst { unsigned int Rd; unsigned int Rm; unsigned int rotate; -} uxtb_inst; +}; -typedef struct _swp_inst { +struct swp_inst { unsigned int Rn; unsigned int Rd; unsigned int Rm; -} swp_inst; +}; -typedef struct setend_inst { +struct setend_inst { unsigned int set_bigend; -} setend_inst; +}; -typedef struct _b_2_thumb { +struct b_2_thumb { unsigned int imm; -}b_2_thumb; -typedef struct _b_cond_thumb { +}; +struct b_cond_thumb { unsigned int imm; unsigned int cond; -}b_cond_thumb; +}; -typedef struct _bl_1_thumb { +struct bl_1_thumb { unsigned int imm; -}bl_1_thumb; -typedef struct _bl_2_thumb { +}; +struct bl_2_thumb { unsigned int imm; -}bl_2_thumb; -typedef struct _blx_1_thumb { +}; +struct blx_1_thumb { unsigned int imm; unsigned int instr; -}blx_1_thumb; +}; -typedef struct _pkh_inst { +struct pkh_inst { unsigned int Rm; unsigned int Rn; unsigned int Rd; unsigned char imm; -} pkh_inst; +}; typedef arm_inst * ARM_INST_PTR; #define CACHE_BUFFER_SIZE (64 * 1024 * 2000) -char inst_buf[CACHE_BUFFER_SIZE]; -int top = 0; -inline void *AllocBuffer(unsigned int size) { +static char inst_buf[CACHE_BUFFER_SIZE]; +static int top = 0; +static inline void *AllocBuffer(unsigned int size) { int start = top; top += size; if (top > CACHE_BUFFER_SIZE) { @@ -1127,74 +1180,6 @@ inline void *AllocBuffer(unsigned int size) { return (void *)&inst_buf[start]; } -int CondPassed(ARMul_State* cpu, unsigned int cond) { - #define NFLAG cpu->NFlag - #define ZFLAG cpu->ZFlag - #define CFLAG cpu->CFlag - #define VFLAG cpu->VFlag - - int temp = 0; - - switch (cond) { - case 0x0: - temp = ZFLAG; - break; - case 0x1: // NE - temp = !ZFLAG; - break; - case 0x6: // VS - temp = VFLAG; - break; - case 0x7: // VC - temp = !VFLAG; - break; - case 0x4: // MI - temp = NFLAG; - break; - case 0x5: // PL - temp = !NFLAG; - break; - case 0x2: // CS - temp = CFLAG; - break; - case 0x3: // CC - temp = !CFLAG; - break; - case 0x8: // HI - temp = (CFLAG && !ZFLAG); - break; - case 0x9: // LS - temp = (!CFLAG || ZFLAG); - break; - case 0xa: // GE - temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG)); - break; - case 0xb: // LT - temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)); - break; - case 0xc: // GT - temp = ((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG)); - break; - case 0xd: // LE - temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG; - break; - case 0xe: // AL - temp = 1; - break; - case 0xf: - temp = 1; - break; - } - return temp; -} - -enum DECODE_STATUS { - DECODE_SUCCESS, - DECODE_FAILURE -}; - -int decode_arm_instr(uint32_t instr, int32_t *idx); - static shtop_fp_t get_shtop(unsigned int inst) { if (BIT(inst, 25)) { return DPO(Immediate); diff --git a/src/core/arm/interpreter/arminit.cpp b/src/core/arm/interpreter/arminit.cpp index 31b2bab06..680a94a39 100644 --- a/src/core/arm/interpreter/arminit.cpp +++ b/src/core/arm/interpreter/arminit.cpp @@ -16,7 +16,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <cstring> -#include "core/mem_map.h" #include "core/arm/skyeye_common/armdefs.h" #include "core/arm/skyeye_common/armemu.h" #include "core/arm/skyeye_common/vfp/vfp.h" diff --git a/src/core/arm/skyeye_common/armmmu.h b/src/core/arm/skyeye_common/armmmu.h index 0463d83c8..c67d7209b 100644 --- a/src/core/arm/skyeye_common/armmmu.h +++ b/src/core/arm/skyeye_common/armmmu.h @@ -22,7 +22,7 @@ #include "common/swap.h" -#include "core/mem_map.h" +#include "core/memory.h" #include "core/arm/skyeye_common/armdefs.h" // Register numbers in the MMU diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp index 72afe2164..a04bf915c 100644 --- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp @@ -13,10 +13,10 @@ /* VMLA */ /* cond 1110 0D00 Vn-- Vd-- 101X N0M0 Vm-- */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vmla_inst { +struct vmla_inst { unsigned int instr; unsigned int dp_operation; -} vmla_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vmla)(unsigned int inst, int index) @@ -63,10 +63,10 @@ VMLA_INST: /* VNMLS */ /* cond 1110 0D00 Vn-- Vd-- 101X N1M0 Vm-- */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vmls_inst { +struct vmls_inst { unsigned int instr; unsigned int dp_operation; -} vmls_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vmls)(unsigned int inst, int index) @@ -113,10 +113,10 @@ VMLS_INST: /* VNMLA */ /* cond 1110 0D01 Vn-- Vd-- 101X N1M0 Vm-- */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vnmla_inst { +struct vnmla_inst { unsigned int instr; unsigned int dp_operation; -} vnmla_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmla)(unsigned int inst, int index) @@ -164,10 +164,10 @@ VNMLA_INST: /* cond 1110 0D01 Vn-- Vd-- 101X N0M0 Vm-- */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vnmls_inst { +struct vnmls_inst { unsigned int instr; unsigned int dp_operation; -} vnmls_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmls)(unsigned int inst, int index) @@ -214,10 +214,10 @@ VNMLS_INST: /* VNMUL */ /* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vnmul_inst { +struct vnmul_inst { unsigned int instr; unsigned int dp_operation; -} vnmul_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmul)(unsigned int inst, int index) @@ -264,10 +264,10 @@ VNMUL_INST: /* VMUL */ /* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vmul_inst { +struct vmul_inst { unsigned int instr; unsigned int dp_operation; -} vmul_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vmul)(unsigned int inst, int index) @@ -314,10 +314,10 @@ VMUL_INST: /* VADD */ /* cond 1110 0D11 Vn-- Vd-- 101X N0M0 Vm-- */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vadd_inst { +struct vadd_inst { unsigned int instr; unsigned int dp_operation; -} vadd_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vadd)(unsigned int inst, int index) @@ -364,10 +364,10 @@ VADD_INST: /* VSUB */ /* cond 1110 0D11 Vn-- Vd-- 101X N1M0 Vm-- */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vsub_inst { +struct vsub_inst { unsigned int instr; unsigned int dp_operation; -} vsub_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vsub)(unsigned int inst, int index) @@ -414,10 +414,10 @@ VSUB_INST: /* VDIV */ /* cond 1110 1D00 Vn-- Vd-- 101X N0M0 Vm-- */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vdiv_inst { +struct vdiv_inst { unsigned int instr; unsigned int dp_operation; -} vdiv_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vdiv)(unsigned int inst, int index) @@ -465,11 +465,11 @@ VDIV_INST: /* cond 1110 1D11 im4H Vd-- 101X 0000 im4L */ /* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vmovi_inst { +struct vmovi_inst { unsigned int single; unsigned int d; unsigned int imm; -} vmovi_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovi)(unsigned int inst, int index) @@ -514,11 +514,11 @@ VMOVI_INST: /* cond 1110 1D11 0000 Vd-- 101X 01M0 Vm-- */ /* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vmovr_inst { +struct vmovr_inst { unsigned int single; unsigned int d; unsigned int m; -} vmovr_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovr)(unsigned int inst, int index) @@ -609,10 +609,10 @@ VABS_INST: /* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vneg_inst { +struct vneg_inst { unsigned int instr; unsigned int dp_operation; -} vneg_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vneg)(unsigned int inst, int index) @@ -659,10 +659,10 @@ VNEG_INST: /* VSQRT */ /* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vsqrt_inst { +struct vsqrt_inst { unsigned int instr; unsigned int dp_operation; -} vsqrt_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vsqrt)(unsigned int inst, int index) @@ -709,10 +709,10 @@ VSQRT_INST: /* VCMP VCMPE */ /* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 1 */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vcmp_inst { +struct vcmp_inst { unsigned int instr; unsigned int dp_operation; -} vcmp_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp)(unsigned int inst, int index) @@ -759,10 +759,10 @@ VCMP_INST: /* VCMP VCMPE */ /* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 2 */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vcmp2_inst { +struct vcmp2_inst { unsigned int instr; unsigned int dp_operation; -} vcmp2_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp2)(unsigned int inst, int index) @@ -809,10 +809,10 @@ VCMP2_INST: /* VCVTBDS between double and single */ /* cond 1110 1D11 0111 Vd-- 101X 11M0 Vm-- */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vcvtbds_inst { +struct vcvtbds_inst { unsigned int instr; unsigned int dp_operation; -} vcvtbds_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbds)(unsigned int inst, int index) @@ -859,10 +859,10 @@ VCVTBDS_INST: /* VCVTBFF between floating point and fixed point */ /* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vcvtbff_inst { +struct vcvtbff_inst { unsigned int instr; unsigned int dp_operation; -} vcvtbff_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbff)(unsigned int inst, int index) @@ -911,10 +911,10 @@ VCVTBFF_INST: /* VCVTBFI between floating point and integer */ /* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vcvtbfi_inst { +struct vcvtbfi_inst { unsigned int instr; unsigned int dp_operation; -} vcvtbfi_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbfi)(unsigned int inst, int index) @@ -967,11 +967,11 @@ VCVTBFI_INST: /* cond 1110 000o Vn-- Rt-- 1010 N001 0000 */ /* cond 1110 op11 CRn- Rt-- copr op21 CRm- MRC */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vmovbrs_inst { +struct vmovbrs_inst { unsigned int to_arm; unsigned int t; unsigned int n; -} vmovbrs_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrs)(unsigned int inst, int index) @@ -1013,10 +1013,10 @@ VMOVBRS_INST: /* cond 1110 1110 reg- Rt-- 1010 0001 0000 */ /* cond 1110 op10 CRn- Rt-- copr op21 CRm- MCR */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vmsr_inst { +struct vmsr_inst { unsigned int reg; unsigned int Rd; -} vmsr_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vmsr)(unsigned int inst, int index) @@ -1040,7 +1040,7 @@ VMSR_INST: { if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled , - and in privilegied mode */ + and in privileged mode */ /* Exceptions must be checked, according to v7 ref manual */ CHECK_VFP_ENABLED; @@ -1060,12 +1060,12 @@ VMSR_INST: /* cond 1110 0XX0 Vd-- Rt-- 1011 DXX1 0000 */ /* cond 1110 op10 CRn- Rt-- copr op21 CRm- MCR */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vmovbrc_inst { +struct vmovbrc_inst { unsigned int esize; unsigned int index; unsigned int d; unsigned int t; -} vmovbrc_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index) @@ -1109,10 +1109,10 @@ VMOVBRC_INST: /* cond 1110 1111 CRn- Rt-- 1010 0001 0000 */ /* cond 1110 op11 CRn- Rt-- copr op21 CRm- MRC */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vmrs_inst { +struct vmrs_inst { unsigned int reg; unsigned int Rt; -} vmrs_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vmrs)(unsigned int inst, int index) @@ -1136,7 +1136,7 @@ VMRS_INST: { if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled, - and in privilegied mode */ + and in privileged mode */ /* Exceptions must be checked, according to v7 ref manual */ CHECK_VFP_ENABLED; @@ -1191,12 +1191,12 @@ VMRS_INST: /* cond 1110 XXX1 Vd-- Rt-- 1011 NXX1 0000 */ /* cond 1110 op11 CRn- Rt-- copr op21 CRm- MCR */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vmovbcr_inst { +struct vmovbcr_inst { unsigned int esize; unsigned int index; unsigned int d; unsigned int t; -} vmovbcr_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index) @@ -1245,12 +1245,12 @@ VMOVBCR_INST: /* cond 1100 010X Rt2- Rt-- 1010 00X1 Vm-- */ /* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vmovbrrss_inst { +struct vmovbrrss_inst { unsigned int to_arm; unsigned int t; unsigned int t2; unsigned int m; -} vmovbrrss_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrss)(unsigned int inst, int index) @@ -1294,12 +1294,12 @@ VMOVBRRSS_INST: /* cond 1100 010X Rt2- Rt-- 1011 00X1 Vm-- */ /* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vmovbrrd_inst { +struct vmovbrrd_inst { unsigned int to_arm; unsigned int t; unsigned int t2; unsigned int m; -} vmovbrrd_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrd)(unsigned int inst, int index) @@ -1347,13 +1347,13 @@ VMOVBRRD_INST: /* VSTR */ /* cond 1101 UD00 Rn-- Vd-- 101X imm8 imm8 */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vstr_inst { +struct vstr_inst { unsigned int single; unsigned int n; unsigned int d; unsigned int imm32; unsigned int add; -} vstr_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vstr)(unsigned int inst, int index) @@ -1415,12 +1415,12 @@ VSTR_INST: /* VPUSH */ /* cond 1101 0D10 1101 Vd-- 101X imm8 imm8 */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vpush_inst { +struct vpush_inst { unsigned int single; unsigned int d; unsigned int imm32; unsigned int regs; -} vpush_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vpush)(unsigned int inst, int index) @@ -1488,7 +1488,7 @@ VPUSH_INST: /* VSTM */ /* cond 110P UDW0 Rn-- Vd-- 101X imm8 imm8 */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vstm_inst { +struct vstm_inst { unsigned int single; unsigned int add; unsigned int wback; @@ -1496,7 +1496,7 @@ typedef struct _vstm_inst { unsigned int n; unsigned int imm32; unsigned int regs; -} vstm_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vstm)(unsigned int inst, int index) @@ -1570,12 +1570,12 @@ VSTM_INST: /* encoding 1 */ /* VPOP */ /* cond 1100 1D11 1101 Vd-- 101X imm8 imm8 */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vpop_inst { +struct vpop_inst { unsigned int single; unsigned int d; unsigned int imm32; unsigned int regs; -} vpop_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vpop)(unsigned int inst, int index) @@ -1643,13 +1643,13 @@ VPOP_INST: /* VLDR */ /* cond 1101 UD01 Rn-- Vd-- 101X imm8 imm8 */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vldr_inst { +struct vldr_inst { unsigned int single; unsigned int n; unsigned int d; unsigned int imm32; unsigned int add; -} vldr_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vldr)(unsigned int inst, int index) @@ -1711,7 +1711,7 @@ VLDR_INST: /* VLDM */ /* cond 110P UDW1 Rn-- Vd-- 101X imm8 imm8 */ #ifdef VFP_INTERPRETER_STRUCT -typedef struct _vldm_inst { +struct vldm_inst { unsigned int single; unsigned int add; unsigned int wback; @@ -1719,7 +1719,7 @@ typedef struct _vldm_inst { unsigned int n; unsigned int imm32; unsigned int regs; -} vldm_inst; +}; #endif #ifdef VFP_INTERPRETER_TRANS static ARM_INST_PTR INTERPRETER_TRANSLATE(vldm)(unsigned int inst, int index) diff --git a/src/core/core.cpp b/src/core/core.cpp index 53aae8c2f..79038cd52 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -8,7 +8,6 @@ #include "core/core.h" #include "core/core_timing.h" -#include "core/mem_map.h" #include "core/settings.h" #include "core/arm/arm_interface.h" #include "core/arm/disassembler/arm_disasm.h" diff --git a/src/core/file_sys/archive_backend.cpp b/src/core/file_sys/archive_backend.cpp index 0439868ab..45a559ce8 100644 --- a/src/core/file_sys/archive_backend.cpp +++ b/src/core/file_sys/archive_backend.cpp @@ -8,7 +8,7 @@ #include "common/string_util.h" #include "core/file_sys/archive_backend.h" -#include "core/mem_map.h" +#include "core/memory.h" namespace FileSys { diff --git a/src/core/hle/config_mem.cpp b/src/core/hle/config_mem.cpp index 35dc9cf58..aea936d2d 100644 --- a/src/core/hle/config_mem.cpp +++ b/src/core/hle/config_mem.cpp @@ -9,59 +9,14 @@ #include "common/common_funcs.h" #include "core/core.h" -#include "core/mem_map.h" +#include "core/memory.h" #include "core/hle/config_mem.h" //////////////////////////////////////////////////////////////////////////////////////////////////// namespace ConfigMem { -struct ConfigMemDef { - u8 kernel_unk; // 0 - u8 kernel_version_rev; // 1 - u8 kernel_version_min; // 2 - u8 kernel_version_maj; // 3 - u32 update_flag; // 4 - u64 ns_tid; // 8 - u32 sys_core_ver; // 10 - u8 unit_info; // 14 - u8 boot_firm; // 15 - u8 prev_firm; // 16 - INSERT_PADDING_BYTES(0x1); // 17 - u32 ctr_sdk_ver; // 18 - INSERT_PADDING_BYTES(0x30 - 0x1C); // 1C - u32 app_mem_type; // 30 - INSERT_PADDING_BYTES(0x40 - 0x34); // 34 - u32 app_mem_alloc; // 40 - u32 sys_mem_alloc; // 44 - u32 base_mem_alloc; // 48 - INSERT_PADDING_BYTES(0x60 - 0x4C); // 4C - u8 firm_unk; // 60 - u8 firm_version_rev; // 61 - u8 firm_version_min; // 62 - u8 firm_version_maj; // 63 - u32 firm_sys_core_ver; // 64 - u32 firm_ctr_sdk_ver; // 68 - INSERT_PADDING_BYTES(0x1000 - 0x6C); // 6C -}; - -static_assert(sizeof(ConfigMemDef) == Memory::CONFIG_MEMORY_SIZE, "Config Memory structure size is wrong"); - -static ConfigMemDef config_mem; - -template <typename T> -inline void Read(T &var, const u32 addr) { - u32 offset = addr - Memory::CONFIG_MEMORY_VADDR; - ASSERT(offset < Memory::CONFIG_MEMORY_SIZE); - var = *(reinterpret_cast<T*>(((uintptr_t)&config_mem) + offset)); -} - -// Explicitly instantiate template functions because we aren't defining this in the header: - -template void Read<u64>(u64 &var, const u32 addr); -template void Read<u32>(u32 &var, const u32 addr); -template void Read<u16>(u16 &var, const u32 addr); -template void Read<u8>(u8 &var, const u32 addr); +ConfigMemDef config_mem; void Init() { std::memset(&config_mem, 0, sizeof(config_mem)); diff --git a/src/core/hle/config_mem.h b/src/core/hle/config_mem.h index cbb478fb3..9825a09e8 100644 --- a/src/core/hle/config_mem.h +++ b/src/core/hle/config_mem.h @@ -9,17 +9,49 @@ // bootrom. Because we're not emulating this, and essentially just "stubbing" the functionality, I'm // putting this as a subset of HLE for now. +#include "common/common_funcs.h" #include "common/common_types.h" +#include "common/swap.h" + +#include "core/memory.h" //////////////////////////////////////////////////////////////////////////////////////////////////// namespace ConfigMem { -template <typename T> -void Read(T &var, const u32 addr); +struct ConfigMemDef { + u8 kernel_unk; // 0 + u8 kernel_version_rev; // 1 + u8 kernel_version_min; // 2 + u8 kernel_version_maj; // 3 + u32_le update_flag; // 4 + u64_le ns_tid; // 8 + u32_le sys_core_ver; // 10 + u8 unit_info; // 14 + u8 boot_firm; // 15 + u8 prev_firm; // 16 + INSERT_PADDING_BYTES(0x1); // 17 + u32_le ctr_sdk_ver; // 18 + INSERT_PADDING_BYTES(0x30 - 0x1C); // 1C + u32_le app_mem_type; // 30 + INSERT_PADDING_BYTES(0x40 - 0x34); // 34 + u32_le app_mem_alloc; // 40 + u32_le sys_mem_alloc; // 44 + u32_le base_mem_alloc; // 48 + INSERT_PADDING_BYTES(0x60 - 0x4C); // 4C + u8 firm_unk; // 60 + u8 firm_version_rev; // 61 + u8 firm_version_min; // 62 + u8 firm_version_maj; // 63 + u32_le firm_sys_core_ver; // 64 + u32_le firm_ctr_sdk_ver; // 68 + INSERT_PADDING_BYTES(0x1000 - 0x6C); // 6C +}; +static_assert(sizeof(ConfigMemDef) == Memory::CONFIG_MEMORY_SIZE, "Config Memory structure size is wrong"); + +extern ConfigMemDef config_mem; void Init(); - void Shutdown(); } // namespace diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index be2626eef..0e5ae29ae 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -7,7 +7,7 @@ #include "common/common_types.h" #include "core/arm/arm_interface.h" -#include "core/mem_map.h" +#include "core/memory.h" #include "core/hle/hle.h" namespace HLE { @@ -102,14 +102,14 @@ template<ResultCode func(u32)> void Wrap() { FuncReturn(func(PARAM(0)).raw); } -template<ResultCode func(s64*, u32, void*, s32)> void Wrap(){ - FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)), +template<ResultCode func(s64*, u32, u32*, s32)> void Wrap(){ + FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), (u32*)Memory::GetPointer(PARAM(2)), (s32)PARAM(3)).raw); } template<ResultCode func(u32*, const char*)> void Wrap() { u32 param_1 = 0; - u32 retval = func(¶m_1, Memory::GetCharPointer(PARAM(1))).raw; + u32 retval = func(¶m_1, (char*)Memory::GetPointer(PARAM(1))).raw; Core::g_app_core->SetReg(1, param_1); FuncReturn(retval); } @@ -163,7 +163,7 @@ template<void func(s64)> void Wrap() { } template<void func(const char*)> void Wrap() { - func(Memory::GetCharPointer(PARAM(0))); + func((char*)Memory::GetPointer(PARAM(0))); } #undef PARAM diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 9d7f6b280..a1221766e 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -5,7 +5,7 @@ #include "common/common_types.h" #include "common/logging/log.h" -#include "core/mem_map.h" +#include "core/memory.h" #include "core/hle/hle.h" #include "core/hle/kernel/address_arbiter.h" diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index b5c98b249..726e4d2ff 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -10,6 +10,7 @@ #include "core/arm/arm_interface.h" #include "core/core.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/thread.h" #include "core/hle/kernel/timer.h" @@ -134,6 +135,7 @@ void HandleTable::Clear() { /// Initialize the kernel void Init() { + Kernel::ResourceLimitsInit(); Kernel::ThreadingInit(); Kernel::TimersInit(); @@ -147,6 +149,7 @@ void Init() { void Shutdown() { Kernel::ThreadingShutdown(); Kernel::TimersShutdown(); + Kernel::ResourceLimitsShutdown(); g_handle_table.Clear(); // Free all kernel objects g_current_process = nullptr; } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 7c106d37c..28748c8f5 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -46,7 +46,8 @@ enum class HandleType : u32 { Process = 8, AddressArbiter = 9, Semaphore = 10, - Timer = 11 + Timer = 11, + ResourceLimit = 12, }; enum { diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 1e439db9e..b5c87e883 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -7,8 +7,9 @@ #include "common/logging/log.h" #include "core/hle/kernel/process.h" +#include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/thread.h" -#include "core/mem_map.h" +#include "core/memory.h" namespace Kernel { diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 90881054c..7b8a68610 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -45,6 +45,8 @@ union ProcessFlags { BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000). }; +class ResourceLimit; + class Process final : public Object { public: static SharedPtr<Process> Create(std::string name, u64 program_id); @@ -61,6 +63,8 @@ public: std::string name; /// Title ID corresponding to the process u64 program_id; + /// Resource limit descriptor for this process + SharedPtr<ResourceLimit> resource_limit; /// The process may only call SVCs which have the corresponding bit set. std::bitset<0x80> svc_access_mask; diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp new file mode 100644 index 000000000..94b3e3298 --- /dev/null +++ b/src/core/hle/kernel/resource_limit.cpp @@ -0,0 +1,157 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <cstring> + +#include "common/logging/log.h" + +#include "core/mem_map.h" +#include "core/hle/kernel/resource_limit.h" + +namespace Kernel { + +static SharedPtr<ResourceLimit> resource_limits[4]; + +ResourceLimit::ResourceLimit() {} +ResourceLimit::~ResourceLimit() {} + +SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) { + SharedPtr<ResourceLimit> resource_limit(new ResourceLimit); + + resource_limit->name = std::move(name); + return resource_limit; +} + +SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) { + switch (category) + { + case ResourceLimitCategory::APPLICATION: + case ResourceLimitCategory::SYS_APPLET: + case ResourceLimitCategory::LIB_APPLET: + case ResourceLimitCategory::OTHER: + return resource_limits[static_cast<u8>(category)]; + default: + LOG_CRITICAL(Kernel, "Unknown resource limit category"); + UNREACHABLE(); + } +} + +s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const { + switch (resource) { + case COMMIT: + return current_commit; + case THREAD: + return current_threads; + case EVENT: + return current_events; + case MUTEX: + return current_mutexes; + case SEMAPHORE: + return current_semaphores; + case TIMER: + return current_timers; + case SHARED_MEMORY: + return current_shared_mems; + case ADDRESS_ARBITER: + return current_address_arbiters; + case CPU_TIME: + return current_cpu_time; + default: + LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); + UNIMPLEMENTED(); + return 0; + } +} + +s32 ResourceLimit::GetMaxResourceValue(u32 resource) const { + switch (resource) { + case COMMIT: + return max_commit; + case THREAD: + return max_threads; + case EVENT: + return max_events; + case MUTEX: + return max_mutexes; + case SEMAPHORE: + return max_semaphores; + case TIMER: + return max_timers; + case SHARED_MEMORY: + return max_shared_mems; + case ADDRESS_ARBITER: + return max_address_arbiters; + case CPU_TIME: + return max_cpu_time; + default: + LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); + UNIMPLEMENTED(); + return 0; + } +} + +void ResourceLimitsInit() { + // Create the four resource limits that the system uses + // Create the APPLICATION resource limit + SharedPtr<ResourceLimit> resource_limit = ResourceLimit::Create("Applications"); + resource_limit->max_priority = 0x18; + resource_limit->max_commit = 0x4000000; + resource_limit->max_threads = 0x20; + resource_limit->max_events = 0x20; + resource_limit->max_mutexes = 0x20; + resource_limit->max_semaphores = 0x8; + resource_limit->max_timers = 0x8; + resource_limit->max_shared_mems = 0x10; + resource_limit->max_address_arbiters = 0x2; + resource_limit->max_cpu_time = 0x1E; + resource_limits[static_cast<u8>(ResourceLimitCategory::APPLICATION)] = resource_limit; + + // Create the SYS_APPLET resource limit + resource_limit = ResourceLimit::Create("System Applets"); + resource_limit->max_priority = 0x4; + resource_limit->max_commit = 0x5E00000; + resource_limit->max_threads = 0x1D; + resource_limit->max_events = 0xB; + resource_limit->max_mutexes = 0x8; + resource_limit->max_semaphores = 0x4; + resource_limit->max_timers = 0x4; + resource_limit->max_shared_mems = 0x8; + resource_limit->max_address_arbiters = 0x3; + resource_limit->max_cpu_time = 0x2710; + resource_limits[static_cast<u8>(ResourceLimitCategory::SYS_APPLET)] = resource_limit; + + // Create the LIB_APPLET resource limit + resource_limit = ResourceLimit::Create("Library Applets"); + resource_limit->max_priority = 0x4; + resource_limit->max_commit = 0x600000; + resource_limit->max_threads = 0xE; + resource_limit->max_events = 0x8; + resource_limit->max_mutexes = 0x8; + resource_limit->max_semaphores = 0x4; + resource_limit->max_timers = 0x4; + resource_limit->max_shared_mems = 0x8; + resource_limit->max_address_arbiters = 0x1; + resource_limit->max_cpu_time = 0x2710; + resource_limits[static_cast<u8>(ResourceLimitCategory::LIB_APPLET)] = resource_limit; + + // Create the OTHER resource limit + resource_limit = ResourceLimit::Create("Others"); + resource_limit->max_priority = 0x4; + resource_limit->max_commit = 0x2180000; + resource_limit->max_threads = 0xE1; + resource_limit->max_events = 0x108; + resource_limit->max_mutexes = 0x25; + resource_limit->max_semaphores = 0x43; + resource_limit->max_timers = 0x2C; + resource_limit->max_shared_mems = 0x1F; + resource_limit->max_address_arbiters = 0x2D; + resource_limit->max_cpu_time = 0x3E8; + resource_limits[static_cast<u8>(ResourceLimitCategory::OTHER)] = resource_limit; +} + +void ResourceLimitsShutdown() { + +} + +} // namespace diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h new file mode 100644 index 000000000..201ec0db9 --- /dev/null +++ b/src/core/hle/kernel/resource_limit.h @@ -0,0 +1,119 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" + +#include "core/hle/kernel/kernel.h" + +namespace Kernel { + +enum class ResourceLimitCategory : u8 { + APPLICATION = 0, + SYS_APPLET = 1, + LIB_APPLET = 2, + OTHER = 3 +}; + +enum ResourceTypes { + PRIORITY = 0, + COMMIT = 1, + THREAD = 2, + EVENT = 3, + MUTEX = 4, + SEMAPHORE = 5, + TIMER = 6, + SHARED_MEMORY = 7, + ADDRESS_ARBITER = 8, + CPU_TIME = 9, +}; + +class ResourceLimit final : public Object { +public: + /** + * Creates a resource limit object. + */ + static SharedPtr<ResourceLimit> Create(std::string name = "Unknown"); + + /** + * Retrieves the resource limit associated with the specified resource limit category. + * @param category The resource limit category + * @returns The resource limit associated with the category + */ + static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category); + + std::string GetTypeName() const override { return "ResourceLimit"; } + std::string GetName() const override { return name; } + + static const HandleType HANDLE_TYPE = HandleType::ResourceLimit; + HandleType GetHandleType() const override { return HANDLE_TYPE; } + + /** + * Gets the current value for the specified resource. + * @param resource Requested resource type + * @returns The current value of the resource type + */ + s32 GetCurrentResourceValue(u32 resource) const; + + /** + * Gets the max value for the specified resource. + * @param resource Requested resource type + * @returns The max value of the resource type + */ + s32 GetMaxResourceValue(u32 resource) const; + + /// Name of resource limit object. + std::string name; + + /// Max thread priority that a process in this category can create + s32 max_priority = 0; + + /// Max memory that processes in this category can use + s32 max_commit = 0; + + ///< Max number of objects that can be collectively created by the processes in this category + s32 max_threads = 0; + s32 max_events = 0; + s32 max_mutexes = 0; + s32 max_semaphores = 0; + s32 max_timers = 0; + s32 max_shared_mems = 0; + s32 max_address_arbiters = 0; + + /// Max CPU time that the processes in this category can utilize + s32 max_cpu_time = 0; + + // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind that + // APPLICATION resource limits should not be affected by the objects created by service modules. + // Currently we have no way of distinguishing if a Create was called by the running application, + // or by a service module. Approach this once we have separated the service modules into their own processes + + /// Current memory that the processes in this category are using + s32 current_commit = 0; + + ///< Current number of objects among all processes in this category + s32 current_threads = 0; + s32 current_events = 0; + s32 current_mutexes = 0; + s32 current_semaphores = 0; + s32 current_timers = 0; + s32 current_shared_mems = 0; + s32 current_address_arbiters = 0; + + /// Current CPU time that the processes in this category are utilizing + s32 current_cpu_time = 0; + +private: + ResourceLimit(); + ~ResourceLimit() override; +}; + +/// Initializes the resource limits +void ResourceLimitsInit(); + +// Destroys the resource limits +void ResourceLimitsShutdown(); + +} // namespace diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h index 8c3886ffd..54a062971 100644 --- a/src/core/hle/kernel/session.h +++ b/src/core/hle/kernel/session.h @@ -6,7 +6,7 @@ #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/thread.h" -#include "core/mem_map.h" +#include "core/memory.h" namespace Kernel { diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index 0c59f4876..4137683b5 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -6,7 +6,7 @@ #include "common/logging/log.h" -#include "core/mem_map.h" +#include "core/memory.h" #include "core/hle/kernel/shared_memory.h" namespace Kernel { diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index afaf0cd5d..a5f1904d7 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -21,7 +21,7 @@ #include "core/hle/kernel/thread.h" #include "core/hle/kernel/mutex.h" #include "core/hle/result.h" -#include "core/mem_map.h" +#include "core/memory.h" namespace Kernel { @@ -495,7 +495,7 @@ void Reschedule() { LOG_TRACE(Kernel, "context switch %u -> %u", cur->GetObjectId(), next->GetObjectId()); } else if (cur) { LOG_TRACE(Kernel, "context switch %u -> idle", cur->GetObjectId()); - } else { + } else if (next) { LOG_TRACE(Kernel, "context switch idle -> %u", next->GetObjectId()); } diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 6b329c12a..389928178 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -12,7 +12,6 @@ #include "common/common_types.h" #include "core/core.h" -#include "core/mem_map.h" #include "core/hle/kernel/kernel.h" #include "core/hle/result.h" diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index c6252a03b..c11c5faba 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp @@ -5,6 +5,7 @@ #include "common/bit_field.h" #include "core/mem_map.h" +#include "core/memory.h" #include "core/hle/kernel/event.h" #include "core/hle/kernel/shared_memory.h" #include "core/hle/result.h" diff --git a/src/core/hle/shared_page.cpp b/src/core/hle/shared_page.cpp index 4f227a370..4014eee98 100644 --- a/src/core/hle/shared_page.cpp +++ b/src/core/hle/shared_page.cpp @@ -8,7 +8,7 @@ #include "common/common_funcs.h" #include "core/core.h" -#include "core/mem_map.h" +#include "core/memory.h" #include "core/hle/config_mem.h" #include "core/hle/shared_page.h" @@ -16,63 +16,12 @@ namespace SharedPage { -// see http://3dbrew.org/wiki/Configuration_Memory#Shared_Memory_Page_For_ARM11_Processes +SharedPageDef shared_page; -#pragma pack(1) -struct DateTime { - u64 date_time; // 0x0 - u64 update_tick; // 0x8 - INSERT_PADDING_BYTES(0x20 - 0x10); // 0x10 -}; - -struct SharedPageDef { - // most of these names are taken from the 3dbrew page linked above. - u32 date_time_selector; // 0x0 - u8 running_hw; // 0x4 - u8 mcu_hw_info; // 0x5: don't know what the acronyms mean - INSERT_PADDING_BYTES(0x20 - 0x6); // 0x6 - DateTime date_time_0; // 0x20 - DateTime date_time_1; // 0x40 - u8 wifi_macaddr[6]; // 0x60 - u8 wifi_unknown1; // 0x66: 3dbrew says these are "Likely wifi hardware related" - u8 wifi_unknown2; // 0x67 - INSERT_PADDING_BYTES(0x80 - 0x68); // 0x68 - float sliderstate_3d; // 0x80 - u8 ledstate_3d; // 0x84 - INSERT_PADDING_BYTES(0xA0 - 0x85); // 0x85 - u64 menu_title_id; // 0xA0 - u64 active_menu_title_id; // 0xA8 - INSERT_PADDING_BYTES(0x1000 - 0xB0); // 0xB0 -}; -#pragma pack() - -static_assert(sizeof(DateTime) == 0x20, "Datetime size is wrong"); -static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE, "Shared page structure size is wrong"); - -static SharedPageDef shared_page; - -template <typename T> -inline void Read(T &var, const u32 addr) { - u32 offset = addr - Memory::SHARED_PAGE_VADDR; - var = *(reinterpret_cast<T*>(((uintptr_t)&shared_page) + offset)); -} - -// Explicitly instantiate template functions because we aren't defining this in the header: -template void Read<u64>(u64 &var, const u32 addr); -template void Read<u32>(u32 &var, const u32 addr); -template void Read<u16>(u16 &var, const u32 addr); -template void Read<u8>(u8 &var, const u32 addr); - -void Set3DSlider(float amount) { +void Init() { std::memset(&shared_page, 0, sizeof(shared_page)); - shared_page.sliderstate_3d = amount; - shared_page.ledstate_3d = (amount == 0.0f); // off when non-zero -} - -void Init() { shared_page.running_hw = 0x1; // product - Set3DSlider(0.0f); } void Shutdown() { diff --git a/src/core/hle/shared_page.h b/src/core/hle/shared_page.h index 1b6e4e581..fd2ab66a2 100644 --- a/src/core/hle/shared_page.h +++ b/src/core/hle/shared_page.h @@ -11,18 +11,46 @@ */ #include "common/common_types.h" +#include "common/swap.h" //////////////////////////////////////////////////////////////////////////////////////////////////// namespace SharedPage { -template <typename T> -void Read(T &var, const u32 addr); - -void Set3DSlider(float amount); +// See http://3dbrew.org/wiki/Configuration_Memory#Shared_Memory_Page_For_ARM11_Processes + +struct DateTime { + u64_le date_time; // 0 + u64_le update_tick; // 8 + INSERT_PADDING_BYTES(0x20 - 0x10); // 10 +}; +static_assert(sizeof(DateTime) == 0x20, "Datetime size is wrong"); + +struct SharedPageDef { + // Most of these names are taken from the 3dbrew page linked above. + u32_le date_time_selector; // 0 + u8 running_hw; // 4 + /// "Microcontroller hardware info" + u8 mcu_hw_info; // 5 + INSERT_PADDING_BYTES(0x20 - 0x6); // 6 + DateTime date_time_0; // 20 + DateTime date_time_1; // 40 + u8 wifi_macaddr[6]; // 60 + u8 wifi_unknown1; // 66 + u8 wifi_unknown2; // 67 + INSERT_PADDING_BYTES(0x80 - 0x68); // 68 + float_le sliderstate_3d; // 80 + u8 ledstate_3d; // 84 + INSERT_PADDING_BYTES(0xA0 - 0x85); // 85 + u64_le menu_title_id; // A0 + u64_le active_menu_title_id; // A8 + INSERT_PADDING_BYTES(0x1000 - 0xB0); // B0 +}; +static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE, "Shared page structure size is wrong"); + +extern SharedPageDef shared_page; void Init(); - void Shutdown(); } // namespace diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index e8159fbdb..654ee2bf6 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -17,6 +17,7 @@ #include "core/hle/kernel/event.h" #include "core/hle/kernel/mutex.h" #include "core/hle/kernel/process.h" +#include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/semaphore.h" #include "core/hle/kernel/shared_memory.h" #include "core/hle/kernel/thread.h" @@ -301,21 +302,47 @@ static void OutputDebugString(const char* string) { } /// Get resource limit -static ResultCode GetResourceLimit(Handle* resource_limit, Handle process) { - // With regards to proceess values: - // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for - // the current KThread. - *resource_limit = 0xDEADBEEF; - LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called process=0x%08X", process); +static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) { + LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); + + SharedPtr<Kernel::Process> process = Kernel::g_handle_table.Get<Kernel::Process>(process_handle); + if (process == nullptr) + return ERR_INVALID_HANDLE; + + CASCADE_RESULT(*resource_limit, Kernel::g_handle_table.Create(process->resource_limit)); + return RESULT_SUCCESS; } /// Get resource limit current values -static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names, +static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle, u32* names, + s32 name_count) { + LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", + resource_limit_handle, names, name_count); + + SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle); + if (resource_limit == nullptr) + return ERR_INVALID_HANDLE; + + for (unsigned int i = 0; i < name_count; ++i) + values[i] = resource_limit->GetCurrentResourceValue(names[i]); + + return RESULT_SUCCESS; +} + +/// Get resource limit max values +static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names, s32 name_count) { - LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%p, name_count=%d", - resource_limit, names, name_count); - Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now + LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", + resource_limit_handle, names, name_count); + + SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle); + if (resource_limit == nullptr) + return ERR_INVALID_HANDLE; + + for (unsigned int i = 0; i < name_count; ++i) + values[i] = resource_limit->GetMaxResourceValue(names[i]); + return RESULT_SUCCESS; } @@ -707,7 +734,7 @@ static const FunctionDef SVC_Table[] = { {0x36, HLE::Wrap<GetProcessIdOfThread>, "GetProcessIdOfThread"}, {0x37, HLE::Wrap<GetThreadId>, "GetThreadId"}, {0x38, HLE::Wrap<GetResourceLimit>, "GetResourceLimit"}, - {0x39, nullptr, "GetResourceLimitLimitValues"}, + {0x39, HLE::Wrap<GetResourceLimitLimitValues>, "GetResourceLimitLimitValues"}, {0x3A, HLE::Wrap<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"}, {0x3B, nullptr, "GetThreadContext"}, {0x3C, nullptr, "Break"}, diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index e4a0e14c4..8ef1f70df 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp @@ -8,7 +8,7 @@ #include "core/settings.h" #include "core/core.h" -#include "core/mem_map.h" +#include "core/memory.h" #include "core/core_timing.h" #include "core/hle/hle.h" diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index e28986085..ad5e929ce 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -9,10 +9,11 @@ #include "core/file_sys/archive_romfs.h" #include "core/hle/kernel/process.h" +#include "core/hle/kernel/resource_limit.h" #include "core/hle/service/fs/archive.h" #include "core/loader/elf.h" #include "core/loader/ncch.h" -#include "core/mem_map.h" +#include "core/memory.h" #include "3dsx.h" @@ -233,6 +234,9 @@ ResultStatus AppLoader_THREEDSX::Load() { Kernel::g_current_process = Kernel::Process::Create(filename, 0); Kernel::g_current_process->svc_access_mask.set(); Kernel::g_current_process->address_mappings = default_address_mappings; + + // Attach the default resource limit (APPLICATION) to the process + Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); Load3DSXFile(*file, Memory::PROCESS_IMAGE_VADDR); diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 47d4e8cea..f00753a79 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -11,8 +11,9 @@ #include "common/symbols.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/resource_limit.h" #include "core/loader/elf.h" -#include "core/mem_map.h" +#include "core/memory.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // ELF Header Constants @@ -354,6 +355,9 @@ ResultStatus AppLoader_ELF::Load() { Kernel::g_current_process->svc_access_mask.set(); Kernel::g_current_process->address_mappings = default_address_mappings; + // Attach the default resource limit (APPLICATION) to the process + Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); + ElfReader elf_reader(&buffer[0]); elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR); // TODO: Fill application title diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 4f881cf6f..8b14edf00 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -13,7 +13,6 @@ #include "core/loader/3dsx.h" #include "core/loader/elf.h" #include "core/loader/ncch.h" -#include "core/mem_map.h" //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index 3325a6ab8..08993c4fa 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -11,8 +11,9 @@ #include "common/swap.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/resource_limit.h" #include "core/loader/ncch.h" -#include "core/mem_map.h" +#include "core/memory.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // Loader namespace @@ -126,6 +127,10 @@ ResultStatus AppLoader_NCCH::LoadExec() const { u64 program_id = *reinterpret_cast<u64_le const*>(&ncch_header.program_id[0]); Kernel::g_current_process = Kernel::Process::Create(process_name, program_id); + // Attach a resource limit to the process based on the resource limit category + Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory( + static_cast<Kernel::ResourceLimitCategory>(exheader_header.arm11_system_local_caps.resource_limit_category)); + // Copy data while converting endianess std::array<u32, ARRAY_SIZE(exheader_header.arm11_kernel_caps.descriptors)> kernel_caps; std::copy_n(exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(), begin(kernel_caps)); diff --git a/src/core/mem_map.cpp b/src/core/mem_map.cpp index f99520464..5ecec9566 100644 --- a/src/core/mem_map.cpp +++ b/src/core/mem_map.cpp @@ -2,10 +2,16 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <map> + #include "common/common_types.h" #include "common/logging/log.h" +#include "core/hle/config_mem.h" +#include "core/hle/shared_page.h" #include "core/mem_map.h" +#include "core/memory.h" +#include "core/memory_setup.h" //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -23,33 +29,129 @@ namespace { struct MemoryArea { u8** ptr; - size_t size; + u32 base; + u32 size; }; // We don't declare the IO regions in here since its handled by other means. static MemoryArea memory_areas[] = { - {&g_exefs_code, PROCESS_IMAGE_MAX_SIZE}, - {&g_heap, HEAP_SIZE }, - {&g_shared_mem, SHARED_MEMORY_SIZE }, - {&g_heap_linear, LINEAR_HEAP_SIZE }, - {&g_vram, VRAM_SIZE }, - {&g_dsp_mem, DSP_RAM_SIZE }, - {&g_tls_mem, TLS_AREA_SIZE }, + {&g_exefs_code, PROCESS_IMAGE_VADDR, PROCESS_IMAGE_MAX_SIZE}, + {&g_heap, HEAP_VADDR, HEAP_SIZE }, + {&g_shared_mem, SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE }, + {&g_heap_linear, LINEAR_HEAP_VADDR, LINEAR_HEAP_SIZE }, + {&g_vram, VRAM_VADDR, VRAM_SIZE }, + {&g_dsp_mem, DSP_RAM_VADDR, DSP_RAM_SIZE }, + {&g_tls_mem, TLS_AREA_VADDR, TLS_AREA_SIZE }, +}; + +/// Represents a block of memory mapped by ControlMemory/MapMemoryBlock +struct MemoryBlock { + MemoryBlock() : handle(0), base_address(0), address(0), size(0), operation(0), permissions(0) { + } + u32 handle; + u32 base_address; + u32 address; + u32 size; + u32 operation; + u32 permissions; + + const u32 GetVirtualAddress() const{ + return base_address + address; + } }; +static std::map<u32, MemoryBlock> heap_map; +static std::map<u32, MemoryBlock> heap_linear_map; + +} + +u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) { + MemoryBlock block; + + block.base_address = HEAP_VADDR; + block.size = size; + block.operation = operation; + block.permissions = permissions; + + if (heap_map.size() > 0) { + const MemoryBlock last_block = heap_map.rbegin()->second; + block.address = last_block.address + last_block.size; + } + heap_map[block.GetVirtualAddress()] = block; + + return block.GetVirtualAddress(); +} + +u32 MapBlock_HeapLinear(u32 size, u32 operation, u32 permissions) { + MemoryBlock block; + + block.base_address = LINEAR_HEAP_VADDR; + block.size = size; + block.operation = operation; + block.permissions = permissions; + + if (heap_linear_map.size() > 0) { + const MemoryBlock last_block = heap_linear_map.rbegin()->second; + block.address = last_block.address + last_block.size; + } + heap_linear_map[block.GetVirtualAddress()] = block; + + return block.GetVirtualAddress(); +} + +PAddr VirtualToPhysicalAddress(const VAddr addr) { + if (addr == 0) { + return 0; + } else if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) { + return addr - VRAM_VADDR + VRAM_PADDR; + } else if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) { + return addr - LINEAR_HEAP_VADDR + FCRAM_PADDR; + } else if (addr >= DSP_RAM_VADDR && addr < DSP_RAM_VADDR_END) { + return addr - DSP_RAM_VADDR + DSP_RAM_PADDR; + } else if (addr >= IO_AREA_VADDR && addr < IO_AREA_VADDR_END) { + return addr - IO_AREA_VADDR + IO_AREA_PADDR; + } + + LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08x", addr); + // To help with debugging, set bit on address so that it's obviously invalid. + return addr | 0x80000000; +} + +VAddr PhysicalToVirtualAddress(const PAddr addr) { + if (addr == 0) { + return 0; + } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) { + return addr - VRAM_PADDR + VRAM_VADDR; + } else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) { + return addr - FCRAM_PADDR + LINEAR_HEAP_VADDR; + } else if (addr >= DSP_RAM_PADDR && addr < DSP_RAM_PADDR_END) { + return addr - DSP_RAM_PADDR + DSP_RAM_VADDR; + } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) { + return addr - IO_AREA_PADDR + IO_AREA_VADDR; + } + + LOG_ERROR(HW_Memory, "Unknown physical address @ 0x%08x", addr); + // To help with debugging, set bit on address so that it's obviously invalid. + return addr | 0x80000000; } void Init() { + InitMemoryMap(); + for (MemoryArea& area : memory_areas) { *area.ptr = new u8[area.size]; + MapMemoryRegion(area.base, area.size, *area.ptr); } - MemBlock_Init(); + MapMemoryRegion(CONFIG_MEMORY_VADDR, CONFIG_MEMORY_SIZE, (u8*)&ConfigMem::config_mem); + MapMemoryRegion(SHARED_PAGE_VADDR, SHARED_PAGE_SIZE, (u8*)&SharedPage::shared_page); LOG_DEBUG(HW_Memory, "initialized OK, RAM at %p", g_heap); } void Shutdown() { - MemBlock_Shutdown(); + heap_map.clear(); + heap_linear_map.clear(); + for (MemoryArea& area : memory_areas) { delete[] *area.ptr; *area.ptr = nullptr; diff --git a/src/core/mem_map.h b/src/core/mem_map.h index 71f90cb8a..945815cd6 100644 --- a/src/core/mem_map.h +++ b/src/core/mem_map.h @@ -8,121 +8,6 @@ namespace Memory { -//////////////////////////////////////////////////////////////////////////////////////////////////// - -const u32 PAGE_SIZE = 0x1000; - -/// Physical memory regions as seen from the ARM11 -enum : PAddr { - /// IO register area - IO_AREA_PADDR = 0x10100000, - IO_AREA_SIZE = 0x01000000, ///< IO area size (16MB) - IO_AREA_PADDR_END = IO_AREA_PADDR + IO_AREA_SIZE, - - /// MPCore internal memory region - MPCORE_RAM_PADDR = 0x17E00000, - MPCORE_RAM_SIZE = 0x00002000, ///< MPCore internal memory size (8KB) - MPCORE_RAM_PADDR_END = MPCORE_RAM_PADDR + MPCORE_RAM_SIZE, - - /// Video memory - VRAM_PADDR = 0x18000000, - VRAM_SIZE = 0x00600000, ///< VRAM size (6MB) - VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE, - - /// DSP memory - DSP_RAM_PADDR = 0x1FF00000, - DSP_RAM_SIZE = 0x00080000, ///< DSP memory size (512KB) - DSP_RAM_PADDR_END = DSP_RAM_PADDR + DSP_RAM_SIZE, - - /// AXI WRAM - AXI_WRAM_PADDR = 0x1FF80000, - AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size (512KB) - AXI_WRAM_PADDR_END = AXI_WRAM_PADDR + AXI_WRAM_SIZE, - - /// Main FCRAM - FCRAM_PADDR = 0x20000000, - FCRAM_SIZE = 0x08000000, ///< FCRAM size (128MB) - FCRAM_PADDR_END = FCRAM_PADDR + FCRAM_SIZE, -}; - -/// Virtual user-space memory regions -enum : VAddr { - /// Where the application text, data and bss reside. - PROCESS_IMAGE_VADDR = 0x00100000, - PROCESS_IMAGE_MAX_SIZE = 0x03F00000, - PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE, - - /// Area where IPC buffers are mapped onto. - IPC_MAPPING_VADDR = 0x04000000, - IPC_MAPPING_SIZE = 0x04000000, - IPC_MAPPING_VADDR_END = IPC_MAPPING_VADDR + IPC_MAPPING_SIZE, - - /// Application heap (includes stack). - HEAP_VADDR = 0x08000000, - HEAP_SIZE = 0x08000000, - HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE, - - /// Area where shared memory buffers are mapped onto. - SHARED_MEMORY_VADDR = 0x10000000, - SHARED_MEMORY_SIZE = 0x04000000, - SHARED_MEMORY_VADDR_END = SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE, - - /// Maps 1:1 to an offset in FCRAM. Used for HW allocations that need to be linear in physical memory. - LINEAR_HEAP_VADDR = 0x14000000, - LINEAR_HEAP_SIZE = 0x08000000, - LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE, - - /// Maps 1:1 to the IO register area. - IO_AREA_VADDR = 0x1EC00000, - IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE, - - /// Maps 1:1 to VRAM. - VRAM_VADDR = 0x1F000000, - VRAM_VADDR_END = VRAM_VADDR + VRAM_SIZE, - - /// Maps 1:1 to DSP memory. - DSP_RAM_VADDR = 0x1FF00000, - DSP_RAM_VADDR_END = DSP_RAM_VADDR + DSP_RAM_SIZE, - - /// Read-only page containing kernel and system configuration values. - CONFIG_MEMORY_VADDR = 0x1FF80000, - CONFIG_MEMORY_SIZE = 0x00001000, - CONFIG_MEMORY_VADDR_END = CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE, - - /// Usually read-only page containing mostly values read from hardware. - SHARED_PAGE_VADDR = 0x1FF81000, - SHARED_PAGE_SIZE = 0x00001000, - SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, - - // TODO(yuriks): The size of this area is dynamic, the kernel grows - // it as more and more threads are created. For now we'll just use a - // hardcoded value. - /// Area where TLS (Thread-Local Storage) buffers are allocated. - TLS_AREA_VADDR = 0x1FF82000, - TLS_AREA_SIZE = 0x00030000, // Each TLS buffer is 0x200 bytes, allows for 300 threads - TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE, -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/// Represents a block of memory mapped by ControlMemory/MapMemoryBlock -struct MemoryBlock { - MemoryBlock() : handle(0), base_address(0), address(0), size(0), operation(0), permissions(0) { - } - u32 handle; - u32 base_address; - u32 address; - u32 size; - u32 operation; - u32 permissions; - - const u32 GetVirtualAddress() const{ - return base_address + address; - } -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - extern u8* g_exefs_code; ///< ExeFS:/.code is loaded here extern u8* g_heap; ///< Application heap (main memory) extern u8* g_shared_mem; ///< Shared memory @@ -134,29 +19,6 @@ extern u8* g_tls_mem; ///< TLS memory void Init(); void Shutdown(); -template <typename T> -inline void Read(T &var, VAddr addr); - -template <typename T> -inline void Write(VAddr addr, T data); - -u8 Read8(VAddr addr); -u16 Read16(VAddr addr); -u32 Read32(VAddr addr); -u64 Read64(VAddr addr); - -u32 Read8_ZX(VAddr addr); -u32 Read16_ZX(VAddr addr); - -void Write8(VAddr addr, u8 data); -void Write16(VAddr addr, u16 data); -void Write32(VAddr addr, u32 data); -void Write64(VAddr addr, u64 data); - -void WriteBlock(VAddr addr, const u8* data, size_t size); - -u8* GetPointer(VAddr virtual_address); - /** * Maps a block of memory on the heap * @param size Size of block in bytes @@ -173,16 +35,6 @@ u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions); */ u32 MapBlock_HeapLinear(u32 size, u32 operation, u32 permissions); -/// Initialize mapped memory blocks -void MemBlock_Init(); - -/// Shutdown mapped memory blocks -void MemBlock_Shutdown(); - -inline const char* GetCharPointer(const VAddr address) { - return (const char *)GetPointer(address); -} - /** * Converts a virtual address inside a region with 1:1 mapping to physical memory to a physical * address. This should be used by services to translate addresses for use by the hardware. @@ -194,13 +46,4 @@ PAddr VirtualToPhysicalAddress(VAddr addr); */ VAddr PhysicalToVirtualAddress(PAddr addr); -/** - * Gets a pointer to the memory region beginning at the specified physical address. - * - * @note This is currently implemented using PhysicalToVirtualAddress(). - */ -inline u8* GetPhysicalPointer(PAddr address) { - return GetPointer(PhysicalToVirtualAddress(address)); -} - } // namespace diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp deleted file mode 100644 index a8e0fed07..000000000 --- a/src/core/mem_map_funcs.cpp +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <map> - -#include "common/common_types.h" -#include "common/logging/log.h" -#include "common/swap.h" - -#include "core/mem_map.h" -#include "core/hw/hw.h" -#include "hle/config_mem.h" -#include "hle/shared_page.h" - -namespace Memory { - -static std::map<u32, MemoryBlock> heap_map; -static std::map<u32, MemoryBlock> heap_linear_map; - -PAddr VirtualToPhysicalAddress(const VAddr addr) { - if (addr == 0) { - return 0; - } else if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) { - return addr - VRAM_VADDR + VRAM_PADDR; - } else if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) { - return addr - LINEAR_HEAP_VADDR + FCRAM_PADDR; - } else if (addr >= DSP_RAM_VADDR && addr < DSP_RAM_VADDR_END) { - return addr - DSP_RAM_VADDR + DSP_RAM_PADDR; - } else if (addr >= IO_AREA_VADDR && addr < IO_AREA_VADDR_END) { - return addr - IO_AREA_VADDR + IO_AREA_PADDR; - } - - LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08x", addr); - // To help with debugging, set bit on address so that it's obviously invalid. - return addr | 0x80000000; -} - -VAddr PhysicalToVirtualAddress(const PAddr addr) { - if (addr == 0) { - return 0; - } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) { - return addr - VRAM_PADDR + VRAM_VADDR; - } else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) { - return addr - FCRAM_PADDR + LINEAR_HEAP_VADDR; - } else if (addr >= DSP_RAM_PADDR && addr < DSP_RAM_PADDR_END) { - return addr - DSP_RAM_PADDR + DSP_RAM_VADDR; - } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) { - return addr - IO_AREA_PADDR + IO_AREA_VADDR; - } - - LOG_ERROR(HW_Memory, "Unknown physical address @ 0x%08x", addr); - // To help with debugging, set bit on address so that it's obviously invalid. - return addr | 0x80000000; -} - -template <typename T> -inline void Read(T &var, const VAddr vaddr) { - // TODO: Figure out the fastest order of tests for both read and write (they are probably different). - // TODO: Make sure this represents the mirrors in a correct way. - // Could just do a base-relative read, too.... TODO - - // Kernel memory command buffer - if (vaddr >= TLS_AREA_VADDR && vaddr < TLS_AREA_VADDR_END) { - var = *((const T*)&g_tls_mem[vaddr - TLS_AREA_VADDR]); - - // ExeFS:/.code is loaded here - } else if ((vaddr >= PROCESS_IMAGE_VADDR) && (vaddr < PROCESS_IMAGE_VADDR_END)) { - var = *((const T*)&g_exefs_code[vaddr - PROCESS_IMAGE_VADDR]); - - // FCRAM - linear heap - } else if ((vaddr >= LINEAR_HEAP_VADDR) && (vaddr < LINEAR_HEAP_VADDR_END)) { - var = *((const T*)&g_heap_linear[vaddr - LINEAR_HEAP_VADDR]); - - // FCRAM - application heap - } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) { - var = *((const T*)&g_heap[vaddr - HEAP_VADDR]); - - // Shared memory - } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) { - var = *((const T*)&g_shared_mem[vaddr - SHARED_MEMORY_VADDR]); - - // Config memory - } else if ((vaddr >= CONFIG_MEMORY_VADDR) && (vaddr < CONFIG_MEMORY_VADDR_END)) { - ConfigMem::Read<T>(var, vaddr); - - // Shared page - } else if ((vaddr >= SHARED_PAGE_VADDR) && (vaddr < SHARED_PAGE_VADDR_END)) { - SharedPage::Read<T>(var, vaddr); - - // DSP memory - } else if ((vaddr >= DSP_RAM_VADDR) && (vaddr < DSP_RAM_VADDR_END)) { - var = *((const T*)&g_dsp_mem[vaddr - DSP_RAM_VADDR]); - - // VRAM - } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) { - var = *((const T*)&g_vram[vaddr - VRAM_VADDR]); - - } else { - LOG_ERROR(HW_Memory, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, vaddr); - } -} - -template <typename T> -inline void Write(const VAddr vaddr, const T data) { - - // Kernel memory command buffer - if (vaddr >= TLS_AREA_VADDR && vaddr < TLS_AREA_VADDR_END) { - *(T*)&g_tls_mem[vaddr - TLS_AREA_VADDR] = data; - - // ExeFS:/.code is loaded here - } else if ((vaddr >= PROCESS_IMAGE_VADDR) && (vaddr < PROCESS_IMAGE_VADDR_END)) { - *(T*)&g_exefs_code[vaddr - PROCESS_IMAGE_VADDR] = data; - - // FCRAM - linear heap - } else if ((vaddr >= LINEAR_HEAP_VADDR) && (vaddr < LINEAR_HEAP_VADDR_END)) { - *(T*)&g_heap_linear[vaddr - LINEAR_HEAP_VADDR] = data; - - // FCRAM - application heap - } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) { - *(T*)&g_heap[vaddr - HEAP_VADDR] = data; - - // Shared memory - } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) { - *(T*)&g_shared_mem[vaddr - SHARED_MEMORY_VADDR] = data; - - // VRAM - } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) { - *(T*)&g_vram[vaddr - VRAM_VADDR] = data; - - // DSP memory - } else if ((vaddr >= DSP_RAM_VADDR) && (vaddr < DSP_RAM_VADDR_END)) { - *(T*)&g_dsp_mem[vaddr - DSP_RAM_VADDR] = data; - - //} else if ((vaddr & 0xFFFF0000) == 0x1FF80000) { - // ASSERT_MSG(MEMMAP, false, "umimplemented write to Configuration Memory"); - //} else if ((vaddr & 0xFFFFF000) == 0x1FF81000) { - // ASSERT_MSG(MEMMAP, false, "umimplemented write to shared page"); - - // Error out... - } else { - LOG_ERROR(HW_Memory, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, vaddr); - } -} - -u8 *GetPointer(const VAddr vaddr) { - // Kernel memory command buffer - if (vaddr >= TLS_AREA_VADDR && vaddr < TLS_AREA_VADDR_END) { - return g_tls_mem + (vaddr - TLS_AREA_VADDR); - - // ExeFS:/.code is loaded here - } else if ((vaddr >= PROCESS_IMAGE_VADDR) && (vaddr < PROCESS_IMAGE_VADDR_END)) { - return g_exefs_code + (vaddr - PROCESS_IMAGE_VADDR); - - // FCRAM - linear heap - } else if ((vaddr >= LINEAR_HEAP_VADDR) && (vaddr < LINEAR_HEAP_VADDR_END)) { - return g_heap_linear + (vaddr - LINEAR_HEAP_VADDR); - - // FCRAM - application heap - } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) { - return g_heap + (vaddr - HEAP_VADDR); - - // Shared memory - } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) { - return g_shared_mem + (vaddr - SHARED_MEMORY_VADDR); - - // VRAM - } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) { - return g_vram + (vaddr - VRAM_VADDR); - - } else { - LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x%08x", vaddr); - return 0; - } -} - -u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) { - MemoryBlock block; - - block.base_address = HEAP_VADDR; - block.size = size; - block.operation = operation; - block.permissions = permissions; - - if (heap_map.size() > 0) { - const MemoryBlock last_block = heap_map.rbegin()->second; - block.address = last_block.address + last_block.size; - } - heap_map[block.GetVirtualAddress()] = block; - - return block.GetVirtualAddress(); -} - -u32 MapBlock_HeapLinear(u32 size, u32 operation, u32 permissions) { - MemoryBlock block; - - block.base_address = LINEAR_HEAP_VADDR; - block.size = size; - block.operation = operation; - block.permissions = permissions; - - if (heap_linear_map.size() > 0) { - const MemoryBlock last_block = heap_linear_map.rbegin()->second; - block.address = last_block.address + last_block.size; - } - heap_linear_map[block.GetVirtualAddress()] = block; - - return block.GetVirtualAddress(); -} - -void MemBlock_Init() { -} - -void MemBlock_Shutdown() { - heap_map.clear(); - heap_linear_map.clear(); -} - -u8 Read8(const VAddr addr) { - u8 data = 0; - Read<u8>(data, addr); - return data; -} - -u16 Read16(const VAddr addr) { - u16_le data = 0; - Read<u16_le>(data, addr); - return (u16)data; -} - -u32 Read32(const VAddr addr) { - u32_le data = 0; - Read<u32_le>(data, addr); - return (u32)data; -} - -u64 Read64(const VAddr addr) { - u64_le data = 0; - Read<u64_le>(data, addr); - return (u64)data; -} - -u32 Read8_ZX(const VAddr addr) { - return (u32)Read8(addr); -} - -u32 Read16_ZX(const VAddr addr) { - return (u32)Read16(addr); -} - -void Write8(const VAddr addr, const u8 data) { - Write<u8>(addr, data); -} - -void Write16(const VAddr addr, const u16 data) { - Write<u16_le>(addr, data); -} - -void Write32(const VAddr addr, const u32 data) { - Write<u32_le>(addr, data); -} - -void Write64(const VAddr addr, const u64 data) { - Write<u64_le>(addr, data); -} - -void WriteBlock(const VAddr addr, const u8* data, const size_t size) { - u32 offset = 0; - while (offset < (size & ~3)) { - Write32(addr + offset, *(u32*)&data[offset]); - offset += 4; - } - - if (size & 2) { - Write16(addr + offset, *(u16*)&data[offset]); - offset += 2; - } - - if (size & 1) - Write8(addr + offset, data[offset]); -} - -} // namespace diff --git a/src/core/memory.cpp b/src/core/memory.cpp new file mode 100644 index 000000000..5d8069acd --- /dev/null +++ b/src/core/memory.cpp @@ -0,0 +1,202 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <array> + +#include "common/assert.h" +#include "common/common_types.h" +#include "common/logging/log.h" +#include "common/swap.h" + +#include "core/hle/config_mem.h" +#include "core/hle/shared_page.h" +#include "core/hw/hw.h" +#include "core/mem_map.h" +#include "core/memory.h" + +namespace Memory { + +const u32 PAGE_MASK = PAGE_SIZE - 1; +const int PAGE_BITS = 12; + +enum class PageType { + /// Page is unmapped and should cause an access error. + Unmapped, + /// Page is mapped to regular memory. This is the only type you can get pointers to. + Memory, + /// Page is mapped to a I/O region. Writing and reading to this page is handled by functions. + Special, +}; + +/** + * A (reasonably) fast way of allowing switchable and remmapable process address spaces. It loosely + * mimics the way a real CPU page table works, but instead is optimized for minimal decoding and + * fetching requirements when acessing. In the usual case of an access to regular memory, it only + * requires an indexed fetch and a check for NULL. + */ +struct PageTable { + static const size_t NUM_ENTRIES = 1 << (32 - PAGE_BITS); + + /** + * Array of memory pointers backing each page. An entry can only be non-null if the + * corresponding entry in the `attributes` array is of type `Memory`. + */ + std::array<u8*, NUM_ENTRIES> pointers; + + /** + * Array of fine grained page attributes. If it is set to any value other than `Memory`, then + * the corresponding entry in `pointer` MUST be set to null. + */ + std::array<PageType, NUM_ENTRIES> attributes; +}; + +/// Singular page table used for the singleton process +static PageTable main_page_table; +/// Currently active page table +static PageTable* current_page_table = &main_page_table; + +static void MapPages(u32 base, u32 size, u8* memory, PageType type) { + LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE, (base + size) * PAGE_SIZE); + + u32 end = base + size; + + while (base != end) { + ASSERT_MSG(base < PageTable::NUM_ENTRIES, "out of range mapping at %08X", base); + + if (current_page_table->attributes[base] != PageType::Unmapped) { + LOG_ERROR(HW_Memory, "overlapping memory ranges at %08X", base * PAGE_SIZE); + } + current_page_table->attributes[base] = type; + current_page_table->pointers[base] = memory; + + base += 1; + memory += PAGE_SIZE; + } +} + +void InitMemoryMap() { + main_page_table.pointers.fill(nullptr); + main_page_table.attributes.fill(PageType::Unmapped); +} + +void MapMemoryRegion(VAddr base, u32 size, u8* target) { + ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: %08X", size); + ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: %08X", base); + MapPages(base / PAGE_SIZE, size / PAGE_SIZE, target, PageType::Memory); +} + +void MapIoRegion(VAddr base, u32 size) { + ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: %08X", size); + ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: %08X", base); + MapPages(base / PAGE_SIZE, size / PAGE_SIZE, nullptr, PageType::Special); +} + +template <typename T> +T Read(const VAddr vaddr) { + const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; + if (page_pointer) { + return *reinterpret_cast<const T*>(page_pointer + (vaddr & PAGE_MASK)); + } + + PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; + switch (type) { + case PageType::Unmapped: + LOG_ERROR(HW_Memory, "unmapped Read%lu @ 0x%08X", sizeof(T) * 8, vaddr); + return 0; + case PageType::Memory: + ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); + case PageType::Special: + LOG_ERROR(HW_Memory, "I/O reads aren't implemented yet @ %08X", vaddr); + return 0; + default: + UNREACHABLE(); + } +} + +template <typename T> +void Write(const VAddr vaddr, const T data) { + u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; + if (page_pointer) { + *reinterpret_cast<T*>(page_pointer + (vaddr & PAGE_MASK)) = data; + return; + } + + PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; + switch (type) { + case PageType::Unmapped: + LOG_ERROR(HW_Memory, "unmapped Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32) data, vaddr); + return; + case PageType::Memory: + ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); + case PageType::Special: + LOG_ERROR(HW_Memory, "I/O writes aren't implemented yet @ %08X", vaddr); + return; + default: + UNREACHABLE(); + } +} + +u8* GetPointer(const VAddr vaddr) { + u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; + if (page_pointer) { + return page_pointer + (vaddr & PAGE_MASK); + } + + LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x%08x", vaddr); + return nullptr; +} + +u8* GetPhysicalPointer(PAddr address) { + return GetPointer(PhysicalToVirtualAddress(address)); +} + +u8 Read8(const VAddr addr) { + return Read<u8>(addr); +} + +u16 Read16(const VAddr addr) { + return Read<u16_le>(addr); +} + +u32 Read32(const VAddr addr) { + return Read<u32_le>(addr); +} + +u64 Read64(const VAddr addr) { + return Read<u64_le>(addr); +} + +void Write8(const VAddr addr, const u8 data) { + Write<u8>(addr, data); +} + +void Write16(const VAddr addr, const u16 data) { + Write<u16_le>(addr, data); +} + +void Write32(const VAddr addr, const u32 data) { + Write<u32_le>(addr, data); +} + +void Write64(const VAddr addr, const u64 data) { + Write<u64_le>(addr, data); +} + +void WriteBlock(const VAddr addr, const u8* data, const size_t size) { + u32 offset = 0; + while (offset < (size & ~3)) { + Write32(addr + offset, *(u32*)&data[offset]); + offset += 4; + } + + if (size & 2) { + Write16(addr + offset, *(u16*)&data[offset]); + offset += 2; + } + + if (size & 1) + Write8(addr + offset, data[offset]); +} + +} // namespace diff --git a/src/core/memory.h b/src/core/memory.h new file mode 100644 index 000000000..2d225801b --- /dev/null +++ b/src/core/memory.h @@ -0,0 +1,129 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" + +namespace Memory { + +/** + * Page size used by the ARM architecture. This is the smallest granularity with which memory can + * be mapped. + */ +const u32 PAGE_SIZE = 0x1000; + +/// Physical memory regions as seen from the ARM11 +enum : PAddr { + /// IO register area + IO_AREA_PADDR = 0x10100000, + IO_AREA_SIZE = 0x01000000, ///< IO area size (16MB) + IO_AREA_PADDR_END = IO_AREA_PADDR + IO_AREA_SIZE, + + /// MPCore internal memory region + MPCORE_RAM_PADDR = 0x17E00000, + MPCORE_RAM_SIZE = 0x00002000, ///< MPCore internal memory size (8KB) + MPCORE_RAM_PADDR_END = MPCORE_RAM_PADDR + MPCORE_RAM_SIZE, + + /// Video memory + VRAM_PADDR = 0x18000000, + VRAM_SIZE = 0x00600000, ///< VRAM size (6MB) + VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE, + + /// DSP memory + DSP_RAM_PADDR = 0x1FF00000, + DSP_RAM_SIZE = 0x00080000, ///< DSP memory size (512KB) + DSP_RAM_PADDR_END = DSP_RAM_PADDR + DSP_RAM_SIZE, + + /// AXI WRAM + AXI_WRAM_PADDR = 0x1FF80000, + AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size (512KB) + AXI_WRAM_PADDR_END = AXI_WRAM_PADDR + AXI_WRAM_SIZE, + + /// Main FCRAM + FCRAM_PADDR = 0x20000000, + FCRAM_SIZE = 0x08000000, ///< FCRAM size (128MB) + FCRAM_PADDR_END = FCRAM_PADDR + FCRAM_SIZE, +}; + +/// Virtual user-space memory regions +enum : VAddr { + /// Where the application text, data and bss reside. + PROCESS_IMAGE_VADDR = 0x00100000, + PROCESS_IMAGE_MAX_SIZE = 0x03F00000, + PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE, + + /// Area where IPC buffers are mapped onto. + IPC_MAPPING_VADDR = 0x04000000, + IPC_MAPPING_SIZE = 0x04000000, + IPC_MAPPING_VADDR_END = IPC_MAPPING_VADDR + IPC_MAPPING_SIZE, + + /// Application heap (includes stack). + HEAP_VADDR = 0x08000000, + HEAP_SIZE = 0x08000000, + HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE, + + /// Area where shared memory buffers are mapped onto. + SHARED_MEMORY_VADDR = 0x10000000, + SHARED_MEMORY_SIZE = 0x04000000, + SHARED_MEMORY_VADDR_END = SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE, + + /// Maps 1:1 to an offset in FCRAM. Used for HW allocations that need to be linear in physical memory. + LINEAR_HEAP_VADDR = 0x14000000, + LINEAR_HEAP_SIZE = 0x08000000, + LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE, + + /// Maps 1:1 to the IO register area. + IO_AREA_VADDR = 0x1EC00000, + IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE, + + /// Maps 1:1 to VRAM. + VRAM_VADDR = 0x1F000000, + VRAM_VADDR_END = VRAM_VADDR + VRAM_SIZE, + + /// Maps 1:1 to DSP memory. + DSP_RAM_VADDR = 0x1FF00000, + DSP_RAM_VADDR_END = DSP_RAM_VADDR + DSP_RAM_SIZE, + + /// Read-only page containing kernel and system configuration values. + CONFIG_MEMORY_VADDR = 0x1FF80000, + CONFIG_MEMORY_SIZE = 0x00001000, + CONFIG_MEMORY_VADDR_END = CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE, + + /// Usually read-only page containing mostly values read from hardware. + SHARED_PAGE_VADDR = 0x1FF81000, + SHARED_PAGE_SIZE = 0x00001000, + SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, + + // TODO(yuriks): The size of this area is dynamic, the kernel grows + // it as more and more threads are created. For now we'll just use a + // hardcoded value. + /// Area where TLS (Thread-Local Storage) buffers are allocated. + TLS_AREA_VADDR = 0x1FF82000, + TLS_AREA_SIZE = 0x00030000, // Each TLS buffer is 0x200 bytes, allows for 300 threads + TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE, +}; + +u8 Read8(VAddr addr); +u16 Read16(VAddr addr); +u32 Read32(VAddr addr); +u64 Read64(VAddr addr); + +void Write8(VAddr addr, u8 data); +void Write16(VAddr addr, u16 data); +void Write32(VAddr addr, u32 data); +void Write64(VAddr addr, u64 data); + +void WriteBlock(VAddr addr, const u8* data, size_t size); + +u8* GetPointer(VAddr virtual_address); + +/** + * Gets a pointer to the memory region beginning at the specified physical address. + * + * @note This is currently implemented using PhysicalToVirtualAddress(). + */ +u8* GetPhysicalPointer(PAddr address); + +} diff --git a/src/core/memory_setup.h b/src/core/memory_setup.h new file mode 100644 index 000000000..46263495f --- /dev/null +++ b/src/core/memory_setup.h @@ -0,0 +1,29 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" + +namespace Memory { + +void InitMemoryMap(); + +/** + * Maps an allocated buffer onto a region of the emulated process address space. + * + * @param base The address to start mapping at. Must be page-aligned. + * @param size The amount of bytes to map. Must be page-aligned. + * @param target Buffer with the memory backing the mapping. Must be of length at least `size`. + */ +void MapMemoryRegion(VAddr base, u32 size, u8* target); + +/** + * Maps a region of the emulated process address space as a IO region. + * @note Currently this can only be used to mark a region as being IO, since actual memory-mapped + * IO isn't yet supported. + */ +void MapIoRegion(VAddr base, u32 size); + +} |