qemu/target/riscv/pmp.h
Jim Shu b297129ae1 target/riscv: propagate PMP permission to TLB page
Currently, PMP permission checking of TLB page is bypassed if TLB hits
Fix it by propagating PMP permission to TLB page permission.

PMP permission checking also use MMU-style API to change TLB permission
and size.

Signed-off-by: Jim Shu <cwshu@andestech.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-id: 1613916082-19528-2-git-send-email-cwshu@andestech.com
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
2021-03-22 21:54:40 -04:00

72 lines
2.3 KiB
C

/*
* QEMU RISC-V PMP (Physical Memory Protection)
*
* Author: Daire McNamara, daire.mcnamara@emdalo.com
* Ivan Griffin, ivan.griffin@emdalo.com
*
* This provides a RISC-V Physical Memory Protection interface
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2 or later, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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 <http://www.gnu.org/licenses/>.
*/
#ifndef RISCV_PMP_H
#define RISCV_PMP_H
typedef enum {
PMP_READ = 1 << 0,
PMP_WRITE = 1 << 1,
PMP_EXEC = 1 << 2,
PMP_LOCK = 1 << 7
} pmp_priv_t;
typedef enum {
PMP_AMATCH_OFF, /* Null (off) */
PMP_AMATCH_TOR, /* Top of Range */
PMP_AMATCH_NA4, /* Naturally aligned four-byte region */
PMP_AMATCH_NAPOT /* Naturally aligned power-of-two region */
} pmp_am_t;
typedef struct {
target_ulong addr_reg;
uint8_t cfg_reg;
} pmp_entry_t;
typedef struct {
target_ulong sa;
target_ulong ea;
} pmp_addr_t;
typedef struct {
pmp_entry_t pmp[MAX_RISCV_PMPS];
pmp_addr_t addr[MAX_RISCV_PMPS];
uint32_t num_rules;
} pmp_table_t;
void pmpcfg_csr_write(CPURISCVState *env, uint32_t reg_index,
target_ulong val);
target_ulong pmpcfg_csr_read(CPURISCVState *env, uint32_t reg_index);
void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index,
target_ulong val);
target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index);
bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
target_ulong size, pmp_priv_t privs, pmp_priv_t *allowed_privs,
target_ulong mode);
bool pmp_is_range_in_tlb(CPURISCVState *env, hwaddr tlb_sa,
target_ulong *tlb_size);
void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index);
void pmp_update_rule_nums(CPURISCVState *env);
uint32_t pmp_get_num_rules(CPURISCVState *env);
int pmp_priv_to_page_prot(pmp_priv_t pmp_priv);
#endif