Merge tag 'pull-ppc-20220104' of https://github.com/legoater/qemu into staging

ppc 7.0 queue:

* Cleanup of PowerNV PHBs (Daniel and Cedric)
* Cleanup and fixes for PPC405 machine (Cedric)
* Fix for xscvspdpn (Matheus)
* Rework of powerpc exception handling 1/n (Fabiano)
* Optimisation for PMU (Richard and Daniel)

# gpg: Signature made Mon 03 Jan 2022 11:04:06 PM PST
# gpg:                using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1
# gpg: Good signature from "Cédric Le Goater <clg@kaod.org>" [undefined]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: A0F6 6548 F048 95EB FE6B  0B60 51A3 43C7 CFFB ECA1

* tag 'pull-ppc-20220104' of https://github.com/legoater/qemu: (26 commits)
  target/ppc: do not call hreg_compute_hflags() in helper_store_mmcr0()
  target/ppc: Use env->pnc_cyc_cnt
  target/ppc: Rewrite pmu_increment_insns
  target/ppc: Cache per-pmc insn and cycle count settings
  target/ppc: powerpc_excp: Stop passing excp_model around
  target/ppc: powerpc_excp: Move system call vectored code together
  target/ppc: powerpc_excp: Set vector earlier
  target/ppc: powerpc_excp: Add excp_vectors bounds check
  target/ppc: powerpc_excp: Set alternate SRRs directly
  target/ppc: do not silence snan in xscvspdpn
  ppc/ppc405: Dump specific registers
  ppc/ppc405: Introduce a store helper for SPR_40x_PID
  ppc/ppc405: Fix timer initialization
  ppc/ppc405: Rework ppc_40x_timers_init() to use a PowerPCCPU
  ppc/ppc405: Restore TCR and STR write handlers
  ppc/ppc405: Activate MMU logs
  ppc/ppc4xx: Convert printfs()
  target/ppc: Print out literal exception names in logs
  target/ppc: Remove static inline
  target/ppc: Check effective address validity
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson
2022-01-04 07:23:27 -08:00
30 changed files with 604 additions and 446 deletions
+2 -1
View File
@@ -1045,7 +1045,8 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp)
memory_region_init(&phb->pci_mmio, OBJECT(phb), "pci-mmio",
PCI_MMIO_TOTAL_SIZE);
pci->bus = pci_register_root_bus(dev, "root-bus",
pci->bus = pci_register_root_bus(dev,
dev->id ? dev->id : NULL,
pnv_phb3_set_irq, pnv_phb3_map_irq, phb,
&phb->pci_mmio, &phb->pci_io,
0, 4, TYPE_PNV_PHB3_ROOT_BUS);
+1 -15
View File
@@ -1201,7 +1201,7 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp)
memory_region_init(&phb->pci_mmio, OBJECT(phb), name,
PCI_MMIO_TOTAL_SIZE);
pci->bus = pci_register_root_bus(dev, "root-bus",
pci->bus = pci_register_root_bus(dev, dev->id,
pnv_phb4_set_irq, pnv_phb4_map_irq, phb,
&phb->pci_mmio, &phb->pci_io,
0, 4, TYPE_PNV_PHB4_ROOT_BUS);
@@ -1230,18 +1230,6 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp)
phb->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc, xsrc->nr_irqs);
}
static void pnv_phb4_reset(DeviceState *dev)
{
PnvPHB4 *phb = PNV_PHB4(dev);
PCIDevice *root_dev = PCI_DEVICE(&phb->root);
/*
* Configure PCI device id at reset using a property.
*/
pci_config_set_vendor_id(root_dev->config, PCI_VENDOR_ID_IBM);
pci_config_set_device_id(root_dev->config, phb->device_id);
}
static const char *pnv_phb4_root_bus_path(PCIHostState *host_bridge,
PCIBus *rootbus)
{
@@ -1274,7 +1262,6 @@ static Property pnv_phb4_properties[] = {
DEFINE_PROP_UINT32("index", PnvPHB4, phb_id, 0),
DEFINE_PROP_UINT32("chip-id", PnvPHB4, chip_id, 0),
DEFINE_PROP_UINT64("version", PnvPHB4, version, 0),
DEFINE_PROP_UINT16("device-id", PnvPHB4, device_id, 0),
DEFINE_PROP_LINK("stack", PnvPHB4, stack, TYPE_PNV_PHB4_PEC_STACK,
PnvPhb4PecStack *),
DEFINE_PROP_END_OF_LIST(),
@@ -1291,7 +1278,6 @@ static void pnv_phb4_class_init(ObjectClass *klass, void *data)
device_class_set_props(dc, pnv_phb4_properties);
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->user_creatable = false;
dc->reset = pnv_phb4_reset;
xfc->notify = pnv_phb4_xive_notify;
}
-3
View File
@@ -527,7 +527,6 @@ static void pnv_pec_class_init(ObjectClass *klass, void *data)
pecc->stk_compat = stk_compat;
pecc->stk_compat_size = sizeof(stk_compat);
pecc->version = PNV_PHB4_VERSION;
pecc->device_id = PNV_PHB4_DEVICE_ID;
pecc->num_stacks = pnv_pec_num_stacks;
}
@@ -587,8 +586,6 @@ static void pnv_pec_stk_realize(DeviceState *dev, Error **errp)
&error_fatal);
object_property_set_int(OBJECT(&stack->phb), "version", pecc->version,
&error_fatal);
object_property_set_int(OBJECT(&stack->phb), "device-id", pecc->device_id,
&error_fatal);
object_property_set_link(OBJECT(&stack->phb), "stack", OBJECT(stack),
&error_abort);
if (!sysbus_realize(SYS_BUS_DEVICE(&stack->phb), errp)) {
+6 -3
View File
@@ -19,6 +19,7 @@
#include "qemu/osdep.h"
#include "qemu/module.h"
#include "qemu/log.h"
#include "sysemu/runstate.h"
#include "cpu.h"
#include "hw/sysbus.h"
@@ -82,7 +83,9 @@ static uint64_t mpc8544_guts_read(void *opaque, hwaddr addr,
value = env->spr[SPR_E500_SVR];
break;
default:
fprintf(stderr, "guts: Unknown register read: %x\n", (int)addr);
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Unknown register 0x%" HWADDR_PRIx "\n",
__func__, addr);
break;
}
@@ -101,8 +104,8 @@ static void mpc8544_guts_write(void *opaque, hwaddr addr,
}
break;
default:
fprintf(stderr, "guts: Unknown register write: %x = %x\n",
(int)addr, (unsigned)value);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Unknown register 0x%" HWADDR_PRIx
" = 0x%" PRIx64 "\n", __func__, addr, value);
break;
}
}
+1 -1
View File
@@ -1314,7 +1314,7 @@ static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */
k->cores_mask = POWER8_CORE_MASK;
k->num_phbs = 3;
k->num_phbs = 4;
k->core_pir = pnv_chip_core_pir_p8;
k->intc_create = pnv_chip_power8_intc_create;
k->intc_reset = pnv_chip_power8_intc_reset;
+44 -23
View File
@@ -1124,14 +1124,12 @@ struct ppc40x_timer_t {
/* Fixed interval timer */
static void cpu_4xx_fit_cb (void *opaque)
{
PowerPCCPU *cpu;
CPUPPCState *env;
PowerPCCPU *cpu = opaque;
CPUPPCState *env = &cpu->env;
ppc_tb_t *tb_env;
ppc40x_timer_t *ppc40x_timer;
uint64_t now, next;
env = opaque;
cpu = env_archcpu(env);
tb_env = env->tb_env;
ppc40x_timer = tb_env->opaque;
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
@@ -1193,13 +1191,11 @@ static void start_stop_pit (CPUPPCState *env, ppc_tb_t *tb_env, int is_excp)
static void cpu_4xx_pit_cb (void *opaque)
{
PowerPCCPU *cpu;
CPUPPCState *env;
PowerPCCPU *cpu = opaque;
CPUPPCState *env = &cpu->env;
ppc_tb_t *tb_env;
ppc40x_timer_t *ppc40x_timer;
env = opaque;
cpu = env_archcpu(env);
tb_env = env->tb_env;
ppc40x_timer = tb_env->opaque;
env->spr[SPR_40x_TSR] |= 1 << 27;
@@ -1216,14 +1212,12 @@ static void cpu_4xx_pit_cb (void *opaque)
/* Watchdog timer */
static void cpu_4xx_wdt_cb (void *opaque)
{
PowerPCCPU *cpu;
CPUPPCState *env;
PowerPCCPU *cpu = opaque;
CPUPPCState *env = &cpu->env;
ppc_tb_t *tb_env;
ppc40x_timer_t *ppc40x_timer;
uint64_t now, next;
env = opaque;
cpu = env_archcpu(env);
tb_env = env->tb_env;
ppc40x_timer = tb_env->opaque;
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
@@ -1300,6 +1294,31 @@ target_ulong load_40x_pit (CPUPPCState *env)
return cpu_ppc_load_decr(env);
}
void store_40x_tsr(CPUPPCState *env, target_ulong val)
{
PowerPCCPU *cpu = env_archcpu(env);
trace_ppc40x_store_tcr(val);
env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
if (val & 0x80000000) {
ppc_set_irq(cpu, PPC_INTERRUPT_PIT, 0);
}
}
void store_40x_tcr(CPUPPCState *env, target_ulong val)
{
PowerPCCPU *cpu = env_archcpu(env);
ppc_tb_t *tb_env;
trace_ppc40x_store_tsr(val);
tb_env = env->tb_env;
env->spr[SPR_40x_TCR] = val & 0xFFC00000;
start_stop_pit(env, tb_env, 1);
cpu_4xx_wdt_cb(cpu);
}
static void ppc_40x_set_tb_clk (void *opaque, uint32_t freq)
{
CPUPPCState *env = opaque;
@@ -1316,24 +1335,26 @@ clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq,
{
ppc_tb_t *tb_env;
ppc40x_timer_t *ppc40x_timer;
PowerPCCPU *cpu = env_archcpu(env);
trace_ppc40x_timers_init(freq);
tb_env = g_malloc0(sizeof(ppc_tb_t));
ppc40x_timer = g_malloc0(sizeof(ppc40x_timer_t));
env->tb_env = tb_env;
tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
ppc40x_timer = g_malloc0(sizeof(ppc40x_timer_t));
tb_env->tb_freq = freq;
tb_env->decr_freq = freq;
tb_env->opaque = ppc40x_timer;
trace_ppc40x_timers_init(freq);
if (ppc40x_timer != NULL) {
/* We use decr timer for PIT */
tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_pit_cb, env);
ppc40x_timer->fit_timer =
timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_fit_cb, env);
ppc40x_timer->wdt_timer =
timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_wdt_cb, env);
ppc40x_timer->decr_excp = decr_excp;
}
/* We use decr timer for PIT */
tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_pit_cb, cpu);
ppc40x_timer->fit_timer =
timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_fit_cb, cpu);
ppc40x_timer->wdt_timer =
timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_wdt_cb, cpu);
ppc40x_timer->decr_excp = decr_excp;
return &ppc_40x_set_tb_clk;
}
-2
View File
@@ -1461,8 +1461,6 @@ PowerPCCPU *ppc405ep_init(MemoryRegion *address_space_mem,
ppc4xx_pob_init(env);
/* OBP arbitrer */
ppc4xx_opba_init(0xef600600);
/* Initialize timers */
ppc_booke_timers_init(cpu, sysclk, 0);
/* Universal interrupt controller */
uicdev = qdev_new(TYPE_PPC_UIC);
uicsbd = SYS_BUS_DEVICE(uicdev);
+11 -28
View File
@@ -35,14 +35,7 @@
#include "exec/address-spaces.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
/*#define DEBUG_UIC*/
#ifdef DEBUG_UIC
# define LOG_UIC(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
#else
# define LOG_UIC(...) do { } while (0)
#endif
#include "trace.h"
static void ppc4xx_reset(void *opaque)
{
@@ -137,8 +130,9 @@ static uint32_t sdram_bcr (hwaddr ram_base,
bcr = 0x000C0000;
break;
default:
printf("%s: invalid RAM size " TARGET_FMT_plx "\n", __func__,
ram_size);
qemu_log_mask(LOG_GUEST_ERROR,
"%s: invalid RAM size 0x%" HWADDR_PRIx "\n", __func__,
ram_size);
return 0x00000000;
}
bcr |= ram_base & 0xFF800000;
@@ -171,10 +165,8 @@ static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i,
{
if (sdram->bcr[i] & 0x00000001) {
/* Unmap RAM */
#ifdef DEBUG_SDRAM
printf("%s: unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
__func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
#endif
trace_ppc4xx_sdram_unmap(sdram_base(sdram->bcr[i]),
sdram_size(sdram->bcr[i]));
memory_region_del_subregion(get_system_memory(),
&sdram->containers[i]);
memory_region_del_subregion(&sdram->containers[i],
@@ -183,10 +175,7 @@ static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i,
}
sdram->bcr[i] = bcr & 0xFFDEE001;
if (enabled && (bcr & 0x00000001)) {
#ifdef DEBUG_SDRAM
printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
__func__, sdram_base(bcr), sdram_size(bcr));
#endif
trace_ppc4xx_sdram_unmap(sdram_base(bcr), sdram_size(bcr));
memory_region_init(&sdram->containers[i], NULL, "sdram-containers",
sdram_size(bcr));
memory_region_add_subregion(&sdram->containers[i], 0,
@@ -216,10 +205,8 @@ static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
int i;
for (i = 0; i < sdram->nbanks; i++) {
#ifdef DEBUG_SDRAM
printf("%s: Unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
__func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
#endif
trace_ppc4xx_sdram_unmap(sdram_base(sdram->bcr[i]),
sdram_size(sdram->bcr[i]));
memory_region_del_subregion(get_system_memory(),
&sdram->ram_memories[i]);
}
@@ -316,16 +303,12 @@ static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val)
case 0x20: /* SDRAM_CFG */
val &= 0xFFE00000;
if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
#ifdef DEBUG_SDRAM
printf("%s: enable SDRAM controller\n", __func__);
#endif
trace_ppc4xx_sdram_enable("enable");
/* validate all RAM mappings */
sdram_map_bcr(sdram);
sdram->status &= ~0x80000000;
} else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
#ifdef DEBUG_SDRAM
printf("%s: disable SDRAM controller\n", __func__);
#endif
trace_ppc4xx_sdram_enable("disable");
/* invalidate all RAM mappings */
sdram_unmap_bcr(sdram);
sdram->status |= 0x80000000;
+7 -4
View File
@@ -20,6 +20,7 @@
* 4xx SoCs, such as the 440EP. */
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "hw/irq.h"
#include "hw/ppc/ppc.h"
#include "hw/ppc/ppc4xx.h"
@@ -152,8 +153,9 @@ static void ppc4xx_pci_reg_write4(void *opaque, hwaddr offset,
break;
default:
printf("%s: unhandled PCI internal register 0x%lx\n", __func__,
(unsigned long)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"%s: unhandled PCI internal register 0x%" HWADDR_PRIx "\n",
__func__, offset);
break;
}
}
@@ -218,8 +220,9 @@ static uint64_t ppc4xx_pci_reg_read4(void *opaque, hwaddr offset,
break;
default:
printf("%s: invalid PCI internal register 0x%lx\n", __func__,
(unsigned long)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"%s: invalid PCI internal register 0x%" HWADDR_PRIx "\n",
__func__, offset);
value = 0;
}
+7
View File
@@ -110,6 +110,8 @@ ppc4xx_pit_start(uint64_t reload) "PIT 0x%016" PRIx64
ppc4xx_pit(uint32_t ar, uint32_t ir, uint64_t tcr, uint64_t tsr, uint64_t reload) "ar %d ir %d TCR 0x%" PRIx64 " TSR 0x%" PRIx64 " PIT 0x%016" PRIx64
ppc4xx_wdt(uint64_t tcr, uint64_t tsr) "TCR 0x%" PRIx64 " TSR 0x%" PRIx64
ppc40x_store_pit(uint64_t value) "val 0x%" PRIx64
ppc40x_store_tcr(uint64_t value) "val 0x%" PRIx64
ppc40x_store_tsr(uint64_t value) "val 0x%" PRIx64
ppc40x_set_tb_clk(uint32_t value) "new frequency %" PRIu32
ppc40x_timers_init(uint32_t value) "frequency %" PRIu32
@@ -164,3 +166,8 @@ ppc4xx_gpt_init(uint64_t addr) "offet 0x%" PRIx64
ppc405ep_clocks_compute(const char *param, uint32_t param2, uint32_t val) "%s 0x%1" PRIx32 " %d"
ppc405ep_clocks_setup(const char *trace) "%s"
# ppc4xx_devs.c
ppc4xx_sdram_enable(const char *trace) "%s SDRAM controller"
ppc4xx_sdram_unmap(uint64_t addr, uint64_t size) "Unmap RAM area 0x%" PRIx64 " size 0x%" PRIx64
ppc4xx_sdram_map(uint64_t addr, uint64_t size) "Map RAM area 0x%" PRIx64 " size 0x%" PRIx64
-2
View File
@@ -84,7 +84,6 @@ struct PnvPHB4 {
uint32_t phb_id;
uint64_t version;
uint16_t device_id;
char bus_path[8];
@@ -222,7 +221,6 @@ struct PnvPhb4PecClass {
const char *stk_compat;
int stk_compat_size;
uint64_t version;
uint64_t device_id;
const uint32_t *num_stacks;
};
+5
View File
@@ -1144,6 +1144,9 @@ struct CPUPPCState {
/* Other registers */
target_ulong spr[1024]; /* special purpose registers */
ppc_spr_t spr_cb[1024];
/* Composite status for PMC[1-6] enabled and counting insns or cycles. */
uint8_t pmc_ins_cnt;
uint8_t pmc_cyc_cnt;
/* Vector status and control register, minus VSCR_SAT */
uint32_t vscr;
/* VSX registers (including FP and AVR) */
@@ -1399,6 +1402,8 @@ target_ulong load_40x_pit(CPUPPCState *env);
void store_40x_pit(CPUPPCState *env, target_ulong val);
void store_40x_dbcr0(CPUPPCState *env, uint32_t val);
void store_40x_sler(CPUPPCState *env, uint32_t val);
void store_40x_tcr(CPUPPCState *env, target_ulong val);
void store_40x_tsr(CPUPPCState *env, target_ulong val);
void store_booke_tcr(CPUPPCState *env, target_ulong val);
void store_booke_tsr(CPUPPCState *env, target_ulong val);
void ppc_tlb_invalidate_all(CPUPPCState *env);
+25 -9
View File
@@ -1440,11 +1440,11 @@ static void register_40x_sprs(CPUPPCState *env)
0x00000000);
spr_register(env, SPR_40x_TCR, "TCR",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_booke_tcr,
&spr_read_generic, &spr_write_40x_tcr,
0x00000000);
spr_register(env, SPR_40x_TSR, "TSR",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_booke_tsr,
&spr_read_generic, &spr_write_40x_tsr,
0x00000000);
}
@@ -1454,7 +1454,7 @@ static void register_405_sprs(CPUPPCState *env)
/* MMU */
spr_register(env, SPR_40x_PID, "PID",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
&spr_read_generic, &spr_write_40x_pid,
0x00000000);
spr_register(env, SPR_4xx_CCR0, "CCR0",
SPR_NOACCESS, SPR_NOACCESS,
@@ -8313,6 +8313,7 @@ static void ppc_cpu_reset(DeviceState *dev)
#endif /* CONFIG_TCG */
#endif
pmu_update_summaries(env);
hreg_compute_hflags(env);
env->reserve_addr = (target_ulong)-1ULL;
/* Be sure no exception or interrupt is pending */
@@ -8648,16 +8649,17 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
env->spr[SPR_SPRG4], env->spr[SPR_SPRG5],
env->spr[SPR_SPRG6], env->spr[SPR_SPRG7]);
switch (env->excp_model) {
#if defined(TARGET_PPC64)
if (env->excp_model == POWERPC_EXCP_POWER7 ||
env->excp_model == POWERPC_EXCP_POWER8 ||
env->excp_model == POWERPC_EXCP_POWER9 ||
env->excp_model == POWERPC_EXCP_POWER10) {
case POWERPC_EXCP_POWER7:
case POWERPC_EXCP_POWER8:
case POWERPC_EXCP_POWER9:
case POWERPC_EXCP_POWER10:
qemu_fprintf(f, "HSRR0 " TARGET_FMT_lx " HSRR1 " TARGET_FMT_lx "\n",
env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
}
break;
#endif
if (env->excp_model == POWERPC_EXCP_BOOKE) {
case POWERPC_EXCP_BOOKE:
qemu_fprintf(f, "CSRR0 " TARGET_FMT_lx " CSRR1 " TARGET_FMT_lx
" MCSRR0 " TARGET_FMT_lx " MCSRR1 " TARGET_FMT_lx "\n",
env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
@@ -8688,6 +8690,20 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
* IVORs are left out as they are large and do not change often --
* they can be read with "p $ivor0", "p $ivor1", etc.
*/
break;
case POWERPC_EXCP_40x:
qemu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx
" ESR " TARGET_FMT_lx " DEAR " TARGET_FMT_lx "\n",
env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
env->spr[SPR_40x_ESR], env->spr[SPR_40x_DEAR]);
qemu_fprintf(f, " EVPR " TARGET_FMT_lx " SRR2 " TARGET_FMT_lx
" SRR3 " TARGET_FMT_lx " PID " TARGET_FMT_lx "\n",
env->spr[SPR_40x_EVPR], env->spr[SPR_40x_SRR2],
env->spr[SPR_40x_SRR3], env->spr[SPR_40x_PID]);
break;
default:
break;
}
#if defined(TARGET_PPC64)
+125 -62
View File
@@ -36,7 +36,79 @@
/* Exception processing */
#if !defined(CONFIG_USER_ONLY)
static inline void dump_syscall(CPUPPCState *env)
static const char *powerpc_excp_name(int excp)
{
switch (excp) {
case POWERPC_EXCP_CRITICAL: return "CRITICAL";
case POWERPC_EXCP_MCHECK: return "MCHECK";
case POWERPC_EXCP_DSI: return "DSI";
case POWERPC_EXCP_ISI: return "ISI";
case POWERPC_EXCP_EXTERNAL: return "EXTERNAL";
case POWERPC_EXCP_ALIGN: return "ALIGN";
case POWERPC_EXCP_PROGRAM: return "PROGRAM";
case POWERPC_EXCP_FPU: return "FPU";
case POWERPC_EXCP_SYSCALL: return "SYSCALL";
case POWERPC_EXCP_APU: return "APU";
case POWERPC_EXCP_DECR: return "DECR";
case POWERPC_EXCP_FIT: return "FIT";
case POWERPC_EXCP_WDT: return "WDT";
case POWERPC_EXCP_DTLB: return "DTLB";
case POWERPC_EXCP_ITLB: return "ITLB";
case POWERPC_EXCP_DEBUG: return "DEBUG";
case POWERPC_EXCP_SPEU: return "SPEU";
case POWERPC_EXCP_EFPDI: return "EFPDI";
case POWERPC_EXCP_EFPRI: return "EFPRI";
case POWERPC_EXCP_EPERFM: return "EPERFM";
case POWERPC_EXCP_DOORI: return "DOORI";
case POWERPC_EXCP_DOORCI: return "DOORCI";
case POWERPC_EXCP_GDOORI: return "GDOORI";
case POWERPC_EXCP_GDOORCI: return "GDOORCI";
case POWERPC_EXCP_HYPPRIV: return "HYPPRIV";
case POWERPC_EXCP_RESET: return "RESET";
case POWERPC_EXCP_DSEG: return "DSEG";
case POWERPC_EXCP_ISEG: return "ISEG";
case POWERPC_EXCP_HDECR: return "HDECR";
case POWERPC_EXCP_TRACE: return "TRACE";
case POWERPC_EXCP_HDSI: return "HDSI";
case POWERPC_EXCP_HISI: return "HISI";
case POWERPC_EXCP_HDSEG: return "HDSEG";
case POWERPC_EXCP_HISEG: return "HISEG";
case POWERPC_EXCP_VPU: return "VPU";
case POWERPC_EXCP_PIT: return "PIT";
case POWERPC_EXCP_IO: return "IO";
case POWERPC_EXCP_RUNM: return "RUNM";
case POWERPC_EXCP_EMUL: return "EMUL";
case POWERPC_EXCP_IFTLB: return "IFTLB";
case POWERPC_EXCP_DLTLB: return "DLTLB";
case POWERPC_EXCP_DSTLB: return "DSTLB";
case POWERPC_EXCP_FPA: return "FPA";
case POWERPC_EXCP_DABR: return "DABR";
case POWERPC_EXCP_IABR: return "IABR";
case POWERPC_EXCP_SMI: return "SMI";
case POWERPC_EXCP_PERFM: return "PERFM";
case POWERPC_EXCP_THERM: return "THERM";
case POWERPC_EXCP_VPUA: return "VPUA";
case POWERPC_EXCP_SOFTP: return "SOFTP";
case POWERPC_EXCP_MAINT: return "MAINT";
case POWERPC_EXCP_MEXTBR: return "MEXTBR";
case POWERPC_EXCP_NMEXTBR: return "NMEXTBR";
case POWERPC_EXCP_ITLBE: return "ITLBE";
case POWERPC_EXCP_DTLBE: return "DTLBE";
case POWERPC_EXCP_VSXU: return "VSXU";
case POWERPC_EXCP_FU: return "FU";
case POWERPC_EXCP_HV_EMU: return "HV_EMU";
case POWERPC_EXCP_HV_MAINT: return "HV_MAINT";
case POWERPC_EXCP_HV_FU: return "HV_FU";
case POWERPC_EXCP_SDOOR: return "SDOOR";
case POWERPC_EXCP_SDOOR_HV: return "SDOOR_HV";
case POWERPC_EXCP_HVIRT: return "HVIRT";
case POWERPC_EXCP_SYSCALL_VECTORED: return "SYSCALL_VECTORED";
default:
g_assert_not_reached();
}
}
static void dump_syscall(CPUPPCState *env)
{
qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64
" r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64
@@ -48,7 +120,7 @@ static inline void dump_syscall(CPUPPCState *env)
ppc_dump_gpr(env, 8), env->nip);
}
static inline void dump_hcall(CPUPPCState *env)
static void dump_hcall(CPUPPCState *env)
{
qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64
" r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
@@ -161,7 +233,7 @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
* | a | h | 11 | 1 | 1 | h |
* +--------------------------------------------------------------------+
*/
static inline void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp,
static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp,
target_ulong msr,
target_ulong *new_msr,
target_ulong *vector)
@@ -258,7 +330,7 @@ static inline void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp,
#endif
}
static inline void powerpc_set_excp_state(PowerPCCPU *cpu,
static void powerpc_set_excp_state(PowerPCCPU *cpu,
target_ulong vector, target_ulong msr)
{
CPUState *cs = CPU(cpu);
@@ -293,15 +365,21 @@ static inline void powerpc_set_excp_state(PowerPCCPU *cpu,
* Note that this function should be greatly optimized when called
* with a constant excp, from ppc_hw_interrupt
*/
static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
static void powerpc_excp(PowerPCCPU *cpu, int excp)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
int excp_model = env->excp_model;
target_ulong msr, new_msr, vector;
int srr0, srr1, asrr0, asrr1, lev = -1;
int srr0, srr1, lev = -1;
if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) {
cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
}
qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
" => %08x (%02x)\n", env->nip, excp, env->error_code);
" => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp),
excp, env->error_code);
/* new srr1 value excluding must-be-zero bits */
if (excp_model == POWERPC_EXCP_BOOKE) {
@@ -319,8 +397,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
/* target registers */
srr0 = SPR_SRR0;
srr1 = SPR_SRR1;
asrr0 = -1;
asrr1 = -1;
/*
* check for special resume at 0x100 from doze/nap/sleep/winkle on
@@ -354,10 +430,15 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
}
#endif
vector = env->excp_vectors[excp];
if (vector == (target_ulong)-1ULL) {
cpu_abort(cs, "Raised an exception without defined vector %d\n",
excp);
}
vector |= env->excp_prefix;
switch (excp) {
case POWERPC_EXCP_NONE:
/* Should never happen */
return;
case POWERPC_EXCP_CRITICAL: /* Critical input */
switch (excp_model) {
case POWERPC_EXCP_40x:
@@ -410,8 +491,9 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
/* FIXME: choose one or the other based on CPU type */
srr0 = SPR_BOOKE_MCSRR0;
srr1 = SPR_BOOKE_MCSRR1;
asrr0 = SPR_BOOKE_CSRR0;
asrr1 = SPR_BOOKE_CSRR1;
env->spr[SPR_BOOKE_CSRR0] = env->nip;
env->spr[SPR_BOOKE_CSRR1] = msr;
break;
default:
break;
@@ -542,6 +624,11 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
env->nip += 4;
new_msr |= env->msr & ((target_ulong)1 << MSR_EE);
new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
vector += lev * 0x20;
env->lr = env->nip;
env->ctr = msr;
break;
case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
@@ -570,8 +657,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
/* FIXME: choose one or the other based on CPU type */
srr0 = SPR_BOOKE_DSRR0;
srr1 = SPR_BOOKE_DSRR1;
asrr0 = SPR_BOOKE_CSRR0;
asrr1 = SPR_BOOKE_CSRR1;
env->spr[SPR_BOOKE_CSRR0] = env->nip;
env->spr[SPR_BOOKE_CSRR1] = msr;
/* DBSR already modified by caller */
} else {
cpu_abort(cs, "Debug exception triggered on unsupported model\n");
@@ -830,22 +919,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
}
#endif
vector = env->excp_vectors[excp];
if (vector == (target_ulong)-1ULL) {
cpu_abort(cs, "Raised an exception without defined vector %d\n",
excp);
}
vector |= env->excp_prefix;
/* If any alternate SRR register are defined, duplicate saved values */
if (asrr0 != -1) {
env->spr[asrr0] = env->nip;
}
if (asrr1 != -1) {
env->spr[asrr1] = msr;
}
#if defined(TARGET_PPC64)
if (excp_model == POWERPC_EXCP_BOOKE) {
if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
@@ -869,14 +942,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
/* Save MSR */
env->spr[srr1] = msr;
#if defined(TARGET_PPC64)
} else {
vector += lev * 0x20;
env->lr = env->nip;
env->ctr = msr;
#endif
}
/* This can update new_msr and vector if AIL applies */
@@ -888,9 +953,8 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
void ppc_cpu_do_interrupt(CPUState *cs)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
powerpc_excp(cpu, env->excp_model, cs->exception_index);
powerpc_excp(cpu, cs->exception_index);
}
static void ppc_hw_interrupt(CPUPPCState *env)
@@ -901,20 +965,20 @@ static void ppc_hw_interrupt(CPUPPCState *env)
/* External reset */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
powerpc_excp(cpu, POWERPC_EXCP_RESET);
return;
}
/* Machine check exception */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK);
powerpc_excp(cpu, POWERPC_EXCP_MCHECK);
return;
}
#if 0 /* TODO */
/* External debug exception */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG);
powerpc_excp(cpu, POWERPC_EXCP_DEBUG);
return;
}
#endif
@@ -934,7 +998,7 @@ static void ppc_hw_interrupt(CPUPPCState *env)
if ((async_deliver || msr_hv == 0) && hdice) {
/* HDEC clears on delivery */
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
powerpc_excp(cpu, POWERPC_EXCP_HDECR);
return;
}
}
@@ -944,7 +1008,7 @@ static void ppc_hw_interrupt(CPUPPCState *env)
/* LPCR will be clear when not supported so this will work */
bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
if ((async_deliver || msr_hv == 0) && hvice) {
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HVIRT);
powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
return;
}
}
@@ -956,14 +1020,14 @@ static void ppc_hw_interrupt(CPUPPCState *env)
/* HEIC blocks delivery to the hypervisor */
if ((async_deliver && !(heic && msr_hv && !msr_pr)) ||
(env->has_hv_mode && msr_hv == 0 && !lpes0)) {
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL);
return;
}
}
if (msr_ce != 0) {
/* External critical interrupt */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL);
powerpc_excp(cpu, POWERPC_EXCP_CRITICAL);
return;
}
}
@@ -971,24 +1035,24 @@ static void ppc_hw_interrupt(CPUPPCState *env)
/* Watchdog timer on embedded PowerPC */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT);
powerpc_excp(cpu, POWERPC_EXCP_WDT);
return;
}
if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI);
powerpc_excp(cpu, POWERPC_EXCP_DOORCI);
return;
}
/* Fixed interval timer on embedded PowerPC */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT);
powerpc_excp(cpu, POWERPC_EXCP_FIT);
return;
}
/* Programmable interval timer on embedded PowerPC */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT);
powerpc_excp(cpu, POWERPC_EXCP_PIT);
return;
}
/* Decrementer exception */
@@ -996,32 +1060,32 @@ static void ppc_hw_interrupt(CPUPPCState *env)
if (ppc_decr_clear_on_delivery(env)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
}
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
powerpc_excp(cpu, POWERPC_EXCP_DECR);
return;
}
if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
if (is_book3s_arch2x(env)) {
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR);
powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
} else {
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
powerpc_excp(cpu, POWERPC_EXCP_DOORI);
}
return;
}
if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDOORBELL)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR_HV);
powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
return;
}
if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM);
powerpc_excp(cpu, POWERPC_EXCP_PERFM);
return;
}
/* Thermal interrupt */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM);
powerpc_excp(cpu, POWERPC_EXCP_THERM);
return;
}
}
@@ -1046,9 +1110,8 @@ static void ppc_hw_interrupt(CPUPPCState *env)
void ppc_cpu_do_system_reset(CPUState *cs)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
powerpc_excp(cpu, POWERPC_EXCP_RESET);
}
void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
@@ -1167,7 +1230,7 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
#endif /* defined(TARGET_PPC64) */
#endif /* CONFIG_TCG */
static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
{
CPUState *cs = env_cpu(env);
+1 -4
View File
@@ -2816,10 +2816,7 @@ uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb)
uint64_t helper_xscvspdpn(CPUPPCState *env, uint64_t xb)
{
float_status tstat = env->fp_status;
set_float_exception_flags(0, &tstat);
return float32_to_float64(xb >> 32, &tstat);
return helper_todouble(xb >> 32);
}
/*
+2
View File
@@ -706,6 +706,8 @@ DEF_HELPER_2(store_hid0_601, void, env, tl)
DEF_HELPER_3(store_403_pbr, void, env, i32, tl)
DEF_HELPER_FLAGS_1(load_40x_pit, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_2(store_40x_pit, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(store_40x_tcr, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(store_40x_tsr, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_2(store_40x_dbcr0, void, env, tl)
DEF_HELPER_2(store_40x_sler, void, env, tl)
DEF_HELPER_FLAGS_2(store_booke_tcr, TCG_CALL_NO_RWG, void, env, tl)
+1 -1
View File
@@ -123,7 +123,7 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
}
#if defined(TARGET_PPC64)
if (pmu_insn_cnt_enabled(env)) {
if (env->pmc_ins_cnt) {
hflags |= 1 << HFLAGS_INSN_CNT;
}
#endif
+2
View File
@@ -8,6 +8,7 @@
#include "qapi/error.h"
#include "qemu/main-loop.h"
#include "kvm_ppc.h"
#include "power8-pmu.h"
static void post_load_update_msr(CPUPPCState *env)
{
@@ -19,6 +20,7 @@ static void post_load_update_msr(CPUPPCState *env)
*/
env->msr ^= env->msr_mask & ~((1ULL << MSR_TGPR) | MSR_HVB);
ppc_store_msr(env, msr);
pmu_update_summaries(env);
}
static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
+57 -3
View File
@@ -32,6 +32,11 @@ static bool ppc_radix64_get_fully_qualified_addr(const CPUPPCState *env,
vaddr eaddr,
uint64_t *lpid, uint64_t *pid)
{
/* When EA(2:11) are nonzero, raise a segment interrupt */
if (eaddr & ~R_EADDR_VALID_MASK) {
return false;
}
if (msr_hv) { /* MSR[HV] -> Hypervisor/bare metal */
switch (eaddr & R_EADDR_QUADRANT) {
case R_EADDR_QUADRANT0:
@@ -97,12 +102,22 @@ static void ppc_radix64_raise_segi(PowerPCCPU *cpu, MMUAccessType access_type,
env->error_code = 0;
}
static inline const char *access_str(MMUAccessType access_type)
{
return access_type == MMU_DATA_LOAD ? "reading" :
(access_type == MMU_DATA_STORE ? "writing" : "execute");
}
static void ppc_radix64_raise_si(PowerPCCPU *cpu, MMUAccessType access_type,
vaddr eaddr, uint32_t cause)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx" cause %08x\n",
__func__, access_str(access_type),
eaddr, cause);
switch (access_type) {
case MMU_INST_FETCH:
/* Instruction Storage Interrupt */
@@ -130,6 +145,11 @@ static void ppc_radix64_raise_hsi(PowerPCCPU *cpu, MMUAccessType access_type,
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx" 0x%"
HWADDR_PRIx" cause %08x\n",
__func__, access_str(access_type),
eaddr, g_raddr, cause);
switch (access_type) {
case MMU_INST_FETCH:
/* H Instruction Storage Interrupt */
@@ -306,6 +326,15 @@ static int ppc_radix64_partition_scoped_xlate(PowerPCCPU *cpu,
hwaddr pte_addr;
uint64_t pte;
qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx
" mmu_idx %u (prot %c%c%c) 0x%"HWADDR_PRIx"\n",
__func__, access_str(access_type),
eaddr, mmu_idx,
*h_prot & PAGE_READ ? 'r' : '-',
*h_prot & PAGE_WRITE ? 'w' : '-',
*h_prot & PAGE_EXEC ? 'x' : '-',
g_raddr);
*h_page_size = PRTBE_R_GET_RTS(pate.dw0);
/* No valid pte or access denied due to protection */
if (ppc_radix64_walk_tree(CPU(cpu)->as, g_raddr, pate.dw0 & PRTBE_R_RPDB,
@@ -343,6 +372,11 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu,
hwaddr h_raddr, pte_addr;
int ret;
qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx
" mmu_idx %u pid %"PRIu64"\n",
__func__, access_str(access_type),
eaddr, mmu_idx, pid);
/* Index Process Table by PID to Find Corresponding Process Table Entry */
offset = pid * sizeof(struct prtb_entry);
size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12);
@@ -468,9 +502,10 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu,
* | = On | Process Scoped | Scoped |
* +-------------+----------------+---------------+
*/
bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
hwaddr *raddr, int *psizep, int *protp, int mmu_idx,
bool guest_visible)
static bool ppc_radix64_xlate_impl(PowerPCCPU *cpu, vaddr eaddr,
MMUAccessType access_type, hwaddr *raddr,
int *psizep, int *protp, int mmu_idx,
bool guest_visible)
{
CPUPPCState *env = &cpu->env;
uint64_t lpid, pid;
@@ -588,3 +623,22 @@ bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
return true;
}
bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
hwaddr *raddrp, int *psizep, int *protp, int mmu_idx,
bool guest_visible)
{
bool ret = ppc_radix64_xlate_impl(cpu, eaddr, access_type, raddrp,
psizep, protp, mmu_idx, guest_visible);
qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx
" mmu_idx %u (prot %c%c%c) -> 0x%"HWADDR_PRIx"\n",
__func__, access_str(access_type),
eaddr, mmu_idx,
*protp & PAGE_READ ? 'r' : '-',
*protp & PAGE_WRITE ? 'w' : '-',
*protp & PAGE_EXEC ? 'x' : '-',
*raddrp);
return ret;
}
+1
View File
@@ -5,6 +5,7 @@
/* Radix Quadrants */
#define R_EADDR_MASK 0x3FFFFFFFFFFFFFFF
#define R_EADDR_VALID_MASK 0xC00FFFFFFFFFFFFF
#define R_EADDR_QUADRANT 0xC000000000000000
#define R_EADDR_QUADRANT0 0x0000000000000000
#define R_EADDR_QUADRANT1 0x4000000000000000

Some files were not shown because too many files have changed in this diff Show More