mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge branch 'ppc-for-upstream' of git://github.com/agraf/qemu
* 'ppc-for-upstream' of git://github.com/agraf/qemu: (58 commits)
target-ppc: Use NARROW_MODE macro for tlbie
target-ppc: Use NARROW_MODE macro for addresses
target-ppc: Use NARROW_MODE macro for comparisons
target-ppc: Use NARROW_MODE macro for branches
target-ppc: Fix add and subf carry generation in narrow mode
target-ppc: Use QOM method dispatch for MMU fault handling
target-ppc: Move ppc tlb_fill implementation into mmu_helper.c
target-ppc: Split user only code out of mmu_helper.c
mmu-hash64: Implement Virtual Page Class Key Protection
mmu-hash*: Merge translate and fault handling functions
mmu-hash*: Don't use full ppc_hash{32, 64}_translate() path for get_phys_page_debug()
mmu-hash*: Correctly mask RPN from hash PTE
mmu-hash*: Clean up real address calculation
mmu-hash*: Clean up PTE flags update
mmu-hash64: Factor SLB N bit into permissions bits
mmu-hash*: Clean up permission checking
mmu-hash32: Remove nx from context structure
mmu-hash*: Don't update PTE flags when permission is denied
mmu-hash32: Don't look up page tables on BAT permission error
mmu-hash32: Cleanup BAT lookup
...
This commit is contained in:
@@ -781,7 +781,8 @@ static int cpu_gdb_write_register(CPUPPCState *env, uint8_t *mem_buf, int n)
|
||||
/* fpscr */
|
||||
if (gdb_has_xml)
|
||||
return 0;
|
||||
return 4;
|
||||
store_fpscr(env, ldtul_p(mem_buf), 0xffffffff);
|
||||
return sizeof(target_ulong);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
+9
-7
@@ -629,7 +629,7 @@ static void ppc_spapr_reset(void)
|
||||
spapr->rtas_size);
|
||||
|
||||
/* Set up the entry state */
|
||||
first_cpu_cpu = CPU(first_cpu);
|
||||
first_cpu_cpu = ENV_GET_CPU(first_cpu);
|
||||
first_cpu->gpr[3] = spapr->fdt_addr;
|
||||
first_cpu->gpr[5] = 0;
|
||||
first_cpu_cpu->halted = 0;
|
||||
@@ -779,6 +779,11 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
|
||||
spapr->htab_shift++;
|
||||
}
|
||||
|
||||
/* Set up Interrupt Controller before we create the VCPUs */
|
||||
spapr->icp = xics_system_init(smp_cpus * kvmppc_smt_threads() / smp_threads,
|
||||
XICS_IRQS);
|
||||
spapr->next_irq = XICS_IRQ_BASE;
|
||||
|
||||
/* init CPUs */
|
||||
if (cpu_model == NULL) {
|
||||
cpu_model = kvm_enabled() ? "host" : "POWER7";
|
||||
@@ -791,6 +796,8 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
|
||||
}
|
||||
env = &cpu->env;
|
||||
|
||||
xics_cpu_setup(spapr->icp, cpu);
|
||||
|
||||
/* Set time-base frequency to 512 MHz */
|
||||
cpu_ppc_tb_init(env, TIMEBASE_FREQ);
|
||||
|
||||
@@ -830,11 +837,6 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
|
||||
}
|
||||
g_free(filename);
|
||||
|
||||
|
||||
/* Set up Interrupt Controller */
|
||||
spapr->icp = xics_system_init(XICS_IRQS);
|
||||
spapr->next_irq = XICS_IRQ_BASE;
|
||||
|
||||
/* Set up EPOW events infrastructure */
|
||||
spapr_events_init(spapr);
|
||||
|
||||
@@ -856,7 +858,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
|
||||
/* Set up PCI */
|
||||
spapr_pci_rtas_init();
|
||||
|
||||
phb = spapr_create_phb(spapr, 0, "pci");
|
||||
phb = spapr_create_phb(spapr, 0);
|
||||
|
||||
for (i = 0; i < nb_nics; i++) {
|
||||
NICInfo *nd = &nd_table[i];
|
||||
|
||||
+35
-67
@@ -3,39 +3,7 @@
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "helper_regs.h"
|
||||
#include "hw/spapr.h"
|
||||
|
||||
#define HPTES_PER_GROUP 8
|
||||
|
||||
#define HPTE_V_SSIZE_SHIFT 62
|
||||
#define HPTE_V_AVPN_SHIFT 7
|
||||
#define HPTE_V_AVPN 0x3fffffffffffff80ULL
|
||||
#define HPTE_V_AVPN_VAL(x) (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT)
|
||||
#define HPTE_V_COMPARE(x, y) (!(((x) ^ (y)) & 0xffffffffffffff80UL))
|
||||
#define HPTE_V_BOLTED 0x0000000000000010ULL
|
||||
#define HPTE_V_LOCK 0x0000000000000008ULL
|
||||
#define HPTE_V_LARGE 0x0000000000000004ULL
|
||||
#define HPTE_V_SECONDARY 0x0000000000000002ULL
|
||||
#define HPTE_V_VALID 0x0000000000000001ULL
|
||||
|
||||
#define HPTE_R_PP0 0x8000000000000000ULL
|
||||
#define HPTE_R_TS 0x4000000000000000ULL
|
||||
#define HPTE_R_KEY_HI 0x3000000000000000ULL
|
||||
#define HPTE_R_RPN_SHIFT 12
|
||||
#define HPTE_R_RPN 0x3ffffffffffff000ULL
|
||||
#define HPTE_R_FLAGS 0x00000000000003ffULL
|
||||
#define HPTE_R_PP 0x0000000000000003ULL
|
||||
#define HPTE_R_N 0x0000000000000004ULL
|
||||
#define HPTE_R_G 0x0000000000000008ULL
|
||||
#define HPTE_R_M 0x0000000000000010ULL
|
||||
#define HPTE_R_I 0x0000000000000020ULL
|
||||
#define HPTE_R_W 0x0000000000000040ULL
|
||||
#define HPTE_R_WIMG 0x0000000000000078ULL
|
||||
#define HPTE_R_C 0x0000000000000080ULL
|
||||
#define HPTE_R_R 0x0000000000000100ULL
|
||||
#define HPTE_R_KEY_LO 0x0000000000000e00ULL
|
||||
|
||||
#define HPTE_V_1TB_SEG 0x4000000000000000ULL
|
||||
#define HPTE_V_VRMA_MASK 0x4001ffffff000000ULL
|
||||
#include "mmu-hash64.h"
|
||||
|
||||
static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
|
||||
target_ulong pte_index)
|
||||
@@ -44,17 +12,17 @@ static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
|
||||
|
||||
rb = (v & ~0x7fULL) << 16; /* AVA field */
|
||||
va_low = pte_index >> 3;
|
||||
if (v & HPTE_V_SECONDARY) {
|
||||
if (v & HPTE64_V_SECONDARY) {
|
||||
va_low = ~va_low;
|
||||
}
|
||||
/* xor vsid from AVA */
|
||||
if (!(v & HPTE_V_1TB_SEG)) {
|
||||
if (!(v & HPTE64_V_1TB_SEG)) {
|
||||
va_low ^= v >> 12;
|
||||
} else {
|
||||
va_low ^= v >> 24;
|
||||
}
|
||||
va_low &= 0x7ff;
|
||||
if (v & HPTE_V_LARGE) {
|
||||
if (v & HPTE64_V_LARGE) {
|
||||
rb |= 1; /* L field */
|
||||
#if 0 /* Disable that P7 specific bit for now */
|
||||
if (r & 0xff000) {
|
||||
@@ -84,10 +52,10 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||
target_ulong page_shift = 12;
|
||||
target_ulong raddr;
|
||||
target_ulong i;
|
||||
uint8_t *hpte;
|
||||
hwaddr hpte;
|
||||
|
||||
/* only handle 4k and 16M pages for now */
|
||||
if (pteh & HPTE_V_LARGE) {
|
||||
if (pteh & HPTE64_V_LARGE) {
|
||||
#if 0 /* We don't support 64k pages yet */
|
||||
if ((ptel & 0xf000) == 0x1000) {
|
||||
/* 64k page */
|
||||
@@ -105,11 +73,11 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||
}
|
||||
}
|
||||
|
||||
raddr = (ptel & HPTE_R_RPN) & ~((1ULL << page_shift) - 1);
|
||||
raddr = (ptel & HPTE64_R_RPN) & ~((1ULL << page_shift) - 1);
|
||||
|
||||
if (raddr < spapr->ram_limit) {
|
||||
/* Regular RAM - should have WIMG=0010 */
|
||||
if ((ptel & HPTE_R_WIMG) != HPTE_R_M) {
|
||||
if ((ptel & HPTE64_R_WIMG) != HPTE64_R_M) {
|
||||
return H_PARAMETER;
|
||||
}
|
||||
} else {
|
||||
@@ -117,7 +85,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||
/* FIXME: What WIMG combinations could be sensible for IO?
|
||||
* For now we allow WIMG=010x, but are there others? */
|
||||
/* FIXME: Should we check against registered IO addresses? */
|
||||
if ((ptel & (HPTE_R_W | HPTE_R_I | HPTE_R_M)) != HPTE_R_I) {
|
||||
if ((ptel & (HPTE64_R_W | HPTE64_R_I | HPTE64_R_M)) != HPTE64_R_I) {
|
||||
return H_PARAMETER;
|
||||
}
|
||||
}
|
||||
@@ -129,26 +97,26 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||
}
|
||||
if (likely((flags & H_EXACT) == 0)) {
|
||||
pte_index &= ~7ULL;
|
||||
hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
|
||||
hpte = pte_index * HASH_PTE_SIZE_64;
|
||||
for (i = 0; ; ++i) {
|
||||
if (i == 8) {
|
||||
return H_PTEG_FULL;
|
||||
}
|
||||
if ((ldq_p(hpte) & HPTE_V_VALID) == 0) {
|
||||
if ((ppc_hash64_load_hpte0(env, hpte) & HPTE64_V_VALID) == 0) {
|
||||
break;
|
||||
}
|
||||
hpte += HASH_PTE_SIZE_64;
|
||||
}
|
||||
} else {
|
||||
i = 0;
|
||||
hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
|
||||
if (ldq_p(hpte) & HPTE_V_VALID) {
|
||||
hpte = pte_index * HASH_PTE_SIZE_64;
|
||||
if (ppc_hash64_load_hpte0(env, hpte) & HPTE64_V_VALID) {
|
||||
return H_PTEG_FULL;
|
||||
}
|
||||
}
|
||||
stq_p(hpte + (HASH_PTE_SIZE_64/2), ptel);
|
||||
ppc_hash64_store_hpte1(env, hpte, ptel);
|
||||
/* eieio(); FIXME: need some sort of barrier for smp? */
|
||||
stq_p(hpte, pteh);
|
||||
ppc_hash64_store_hpte0(env, hpte, pteh);
|
||||
|
||||
args[0] = pte_index + i;
|
||||
return H_SUCCESS;
|
||||
@@ -166,26 +134,26 @@ static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex,
|
||||
target_ulong flags,
|
||||
target_ulong *vp, target_ulong *rp)
|
||||
{
|
||||
uint8_t *hpte;
|
||||
hwaddr hpte;
|
||||
target_ulong v, r, rb;
|
||||
|
||||
if ((ptex * HASH_PTE_SIZE_64) & ~env->htab_mask) {
|
||||
return REMOVE_PARM;
|
||||
}
|
||||
|
||||
hpte = env->external_htab + (ptex * HASH_PTE_SIZE_64);
|
||||
hpte = ptex * HASH_PTE_SIZE_64;
|
||||
|
||||
v = ldq_p(hpte);
|
||||
r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
|
||||
v = ppc_hash64_load_hpte0(env, hpte);
|
||||
r = ppc_hash64_load_hpte1(env, hpte);
|
||||
|
||||
if ((v & HPTE_V_VALID) == 0 ||
|
||||
if ((v & HPTE64_V_VALID) == 0 ||
|
||||
((flags & H_AVPN) && (v & ~0x7fULL) != avpn) ||
|
||||
((flags & H_ANDCOND) && (v & avpn) != 0)) {
|
||||
return REMOVE_NOT_FOUND;
|
||||
}
|
||||
*vp = v;
|
||||
*rp = r;
|
||||
stq_p(hpte, 0);
|
||||
ppc_hash64_store_hpte0(env, hpte, 0);
|
||||
rb = compute_tlbie_rb(v, r, ptex);
|
||||
ppc_tlb_invalidate_one(env, rb);
|
||||
return REMOVE_SUCCESS;
|
||||
@@ -271,7 +239,7 @@ static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||
|
||||
switch (ret) {
|
||||
case REMOVE_SUCCESS:
|
||||
*tsh |= (r & (HPTE_R_C | HPTE_R_R)) << 43;
|
||||
*tsh |= (r & (HPTE64_R_C | HPTE64_R_R)) << 43;
|
||||
break;
|
||||
|
||||
case REMOVE_PARM:
|
||||
@@ -292,34 +260,34 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||
target_ulong flags = args[0];
|
||||
target_ulong pte_index = args[1];
|
||||
target_ulong avpn = args[2];
|
||||
uint8_t *hpte;
|
||||
hwaddr hpte;
|
||||
target_ulong v, r, rb;
|
||||
|
||||
if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
|
||||
return H_PARAMETER;
|
||||
}
|
||||
|
||||
hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
|
||||
hpte = pte_index * HASH_PTE_SIZE_64;
|
||||
|
||||
v = ldq_p(hpte);
|
||||
r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
|
||||
v = ppc_hash64_load_hpte0(env, hpte);
|
||||
r = ppc_hash64_load_hpte1(env, hpte);
|
||||
|
||||
if ((v & HPTE_V_VALID) == 0 ||
|
||||
if ((v & HPTE64_V_VALID) == 0 ||
|
||||
((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) {
|
||||
return H_NOT_FOUND;
|
||||
}
|
||||
|
||||
r &= ~(HPTE_R_PP0 | HPTE_R_PP | HPTE_R_N |
|
||||
HPTE_R_KEY_HI | HPTE_R_KEY_LO);
|
||||
r |= (flags << 55) & HPTE_R_PP0;
|
||||
r |= (flags << 48) & HPTE_R_KEY_HI;
|
||||
r |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
|
||||
r &= ~(HPTE64_R_PP0 | HPTE64_R_PP | HPTE64_R_N |
|
||||
HPTE64_R_KEY_HI | HPTE64_R_KEY_LO);
|
||||
r |= (flags << 55) & HPTE64_R_PP0;
|
||||
r |= (flags << 48) & HPTE64_R_KEY_HI;
|
||||
r |= flags & (HPTE64_R_PP | HPTE64_R_N | HPTE64_R_KEY_LO);
|
||||
rb = compute_tlbie_rb(v, r, pte_index);
|
||||
stq_p(hpte, v & ~HPTE_V_VALID);
|
||||
ppc_hash64_store_hpte0(env, hpte, v & ~HPTE64_V_VALID);
|
||||
ppc_tlb_invalidate_one(env, rb);
|
||||
stq_p(hpte + (HASH_PTE_SIZE_64/2), r);
|
||||
ppc_hash64_store_hpte1(env, hpte, r);
|
||||
/* Don't need a memory barrier, due to qemu's global lock */
|
||||
stq_p(hpte, v);
|
||||
ppc_hash64_store_hpte0(env, hpte, v);
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
+26
-33
@@ -521,46 +521,39 @@ static void xics_reset(void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
struct icp_state *xics_system_init(int nr_irqs)
|
||||
void xics_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu)
|
||||
{
|
||||
CPUState *cs = CPU(cpu);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
struct icp_server_state *ss = &icp->ss[cs->cpu_index];
|
||||
|
||||
assert(cs->cpu_index < icp->nr_servers);
|
||||
|
||||
switch (PPC_INPUT(env)) {
|
||||
case PPC_FLAGS_INPUT_POWER7:
|
||||
ss->output = env->irq_inputs[POWER7_INPUT_INT];
|
||||
break;
|
||||
|
||||
case PPC_FLAGS_INPUT_970:
|
||||
ss->output = env->irq_inputs[PPC970_INPUT_INT];
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "XICS interrupt controller does not support this CPU "
|
||||
"bus model\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
struct icp_state *xics_system_init(int nr_servers, int nr_irqs)
|
||||
{
|
||||
CPUPPCState *env;
|
||||
CPUState *cpu;
|
||||
int max_server_num;
|
||||
struct icp_state *icp;
|
||||
struct ics_state *ics;
|
||||
|
||||
max_server_num = -1;
|
||||
for (env = first_cpu; env != NULL; env = env->next_cpu) {
|
||||
cpu = CPU(ppc_env_get_cpu(env));
|
||||
if (cpu->cpu_index > max_server_num) {
|
||||
max_server_num = cpu->cpu_index;
|
||||
}
|
||||
}
|
||||
|
||||
icp = g_malloc0(sizeof(*icp));
|
||||
icp->nr_servers = max_server_num + 1;
|
||||
icp->nr_servers = nr_servers;
|
||||
icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state));
|
||||
|
||||
for (env = first_cpu; env != NULL; env = env->next_cpu) {
|
||||
cpu = CPU(ppc_env_get_cpu(env));
|
||||
struct icp_server_state *ss = &icp->ss[cpu->cpu_index];
|
||||
|
||||
switch (PPC_INPUT(env)) {
|
||||
case PPC_FLAGS_INPUT_POWER7:
|
||||
ss->output = env->irq_inputs[POWER7_INPUT_INT];
|
||||
break;
|
||||
|
||||
case PPC_FLAGS_INPUT_970:
|
||||
ss->output = env->irq_inputs[PPC970_INPUT_INT];
|
||||
break;
|
||||
|
||||
default:
|
||||
hw_error("XICS interrupt model does not support this CPU bus "
|
||||
"model\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
ics = g_malloc0(sizeof(*ics));
|
||||
ics->nr_irqs = nr_irqs;
|
||||
ics->offset = XICS_IRQ_BASE;
|
||||
|
||||
+22
-8
@@ -518,6 +518,7 @@ static int spapr_phb_init(SysBusDevice *s)
|
||||
{
|
||||
sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s);
|
||||
const char *busname;
|
||||
char *namebuf;
|
||||
int i;
|
||||
PCIBus *bus;
|
||||
@@ -575,9 +576,6 @@ static int spapr_phb_init(SysBusDevice *s)
|
||||
}
|
||||
|
||||
sphb->dtbusname = g_strdup_printf("pci@%" PRIx64, sphb->buid);
|
||||
if (!sphb->busname) {
|
||||
sphb->busname = sphb->dtbusname;
|
||||
}
|
||||
|
||||
namebuf = alloca(strlen(sphb->dtbusname) + 32);
|
||||
|
||||
@@ -621,7 +619,26 @@ static int spapr_phb_init(SysBusDevice *s)
|
||||
&sphb->msiwindow);
|
||||
}
|
||||
|
||||
bus = pci_register_bus(DEVICE(s), sphb->busname,
|
||||
/*
|
||||
* Selecting a busname is more complex than you'd think, due to
|
||||
* interacting constraints. If the user has specified an id
|
||||
* explicitly for the phb , then we want to use the qdev default
|
||||
* of naming the bus based on the bridge device (so the user can
|
||||
* then assign devices to it in the way they expect). For the
|
||||
* first / default PCI bus (index=0) we want to use just "pci"
|
||||
* because libvirt expects there to be a bus called, simply,
|
||||
* "pci". Otherwise, we use the same name as in the device tree,
|
||||
* since it's unique by construction, and makes the guest visible
|
||||
* BUID clear.
|
||||
*/
|
||||
if (s->qdev.id) {
|
||||
busname = NULL;
|
||||
} else if (sphb->index == 0) {
|
||||
busname = "pci";
|
||||
} else {
|
||||
busname = sphb->dtbusname;
|
||||
}
|
||||
bus = pci_register_bus(DEVICE(s), busname,
|
||||
pci_spapr_set_irq, pci_spapr_map_irq, sphb,
|
||||
&sphb->memspace, &sphb->iospace,
|
||||
PCI_DEVFN(0, 0), PCI_NUM_PINS);
|
||||
@@ -663,7 +680,6 @@ static void spapr_phb_reset(DeviceState *qdev)
|
||||
}
|
||||
|
||||
static Property spapr_phb_properties[] = {
|
||||
DEFINE_PROP_STRING("busname", sPAPRPHBState, busname),
|
||||
DEFINE_PROP_INT32("index", sPAPRPHBState, index, -1),
|
||||
DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, -1),
|
||||
DEFINE_PROP_HEX32("liobn", sPAPRPHBState, dma_liobn, -1),
|
||||
@@ -694,14 +710,12 @@ static const TypeInfo spapr_phb_info = {
|
||||
.class_init = spapr_phb_class_init,
|
||||
};
|
||||
|
||||
PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index,
|
||||
const char *busname)
|
||||
PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
||||
dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE);
|
||||
qdev_prop_set_uint32(dev, "index", index);
|
||||
qdev_prop_set_string(dev, "busname", busname);
|
||||
qdev_init_nofail(dev);
|
||||
|
||||
return PCI_HOST_BRIDGE(dev);
|
||||
|
||||
+1
-3
@@ -39,7 +39,6 @@ typedef struct sPAPRPHBState {
|
||||
|
||||
int32_t index;
|
||||
uint64_t buid;
|
||||
char *busname;
|
||||
char *dtbusname;
|
||||
|
||||
MemoryRegion memspace, iospace;
|
||||
@@ -82,8 +81,7 @@ static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin)
|
||||
return xics_get_qirq(spapr->icp, phb->lsi_table[pin].irq);
|
||||
}
|
||||
|
||||
PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index,
|
||||
const char *busname);
|
||||
PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index);
|
||||
|
||||
int spapr_populate_pci_dt(sPAPRPHBState *phb,
|
||||
uint32_t xics_phandle,
|
||||
|
||||
@@ -35,6 +35,7 @@ struct icp_state;
|
||||
qemu_irq xics_get_qirq(struct icp_state *icp, int irq);
|
||||
void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi);
|
||||
|
||||
struct icp_state *xics_system_init(int nr_irqs);
|
||||
struct icp_state *xics_system_init(int nr_servers, int nr_irqs);
|
||||
void xics_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu);
|
||||
|
||||
#endif /* __XICS_H__ */
|
||||
|
||||
@@ -2960,10 +2960,6 @@ static const MonitorDef monitor_defs[] = {
|
||||
{ "xer", 0, &monitor_get_xer, },
|
||||
{ "tbu", 0, &monitor_get_tbu, },
|
||||
{ "tbl", 0, &monitor_get_tbl, },
|
||||
#if defined(TARGET_PPC64)
|
||||
/* Address space register */
|
||||
{ "asr", offsetof(CPUPPCState, asr) },
|
||||
#endif
|
||||
/* Segment registers */
|
||||
{ "sdr1", offsetof(CPUPPCState, spr[SPR_SDR1]) },
|
||||
{ "sr0", offsetof(CPUPPCState, sr[0]) },
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
obj-y += cpu-models.o
|
||||
obj-y += translate.o
|
||||
obj-$(CONFIG_SOFTMMU) += machine.o
|
||||
ifeq ($(CONFIG_SOFTMMU),y)
|
||||
obj-y += machine.o mmu_helper.o mmu-hash32.o
|
||||
obj-$(TARGET_PPC64) += mmu-hash64.o
|
||||
endif
|
||||
obj-$(CONFIG_KVM) += kvm.o kvm_ppc.o
|
||||
obj-y += excp_helper.o
|
||||
obj-y += fpu_helper.o
|
||||
obj-y += int_helper.o
|
||||
obj-y += mmu_helper.o
|
||||
obj-y += timebase_helper.o
|
||||
obj-y += misc_helper.o
|
||||
obj-y += mem_helper.o
|
||||
obj-$(CONFIG_USER_ONLY) += user_only_helper.o
|
||||
|
||||
@@ -1101,9 +1101,9 @@
|
||||
"PowerPC 7457A v1.2 (G4)")
|
||||
/* 64 bits PowerPC */
|
||||
#if defined (TARGET_PPC64)
|
||||
#if defined(TODO)
|
||||
POWERPC_DEF("620", CPU_POWERPC_620, 620,
|
||||
"PowerPC 620")
|
||||
#if defined(TODO)
|
||||
POWERPC_DEF("630", CPU_POWERPC_630, 630,
|
||||
"PowerPC 630 (POWER3)")
|
||||
#endif
|
||||
|
||||
@@ -68,6 +68,10 @@ typedef struct PowerPCCPUClass {
|
||||
#endif
|
||||
void (*init_proc)(CPUPPCState *env);
|
||||
int (*check_pow)(CPUPPCState *env);
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
int (*handle_mmu_fault)(CPUPPCState *env, target_ulong eaddr, int rwx,
|
||||
int mmu_idx);
|
||||
#endif
|
||||
} PowerPCCPUClass;
|
||||
|
||||
/**
|
||||
|
||||
+12
-79
@@ -113,13 +113,13 @@ enum powerpc_mmu_t {
|
||||
#if defined(TARGET_PPC64)
|
||||
#define POWERPC_MMU_64 0x00010000
|
||||
#define POWERPC_MMU_1TSEG 0x00020000
|
||||
#define POWERPC_MMU_AMR 0x00040000
|
||||
/* 64 bits PowerPC MMU */
|
||||
POWERPC_MMU_64B = POWERPC_MMU_64 | 0x00000001,
|
||||
/* 620 variant (no segment exceptions) */
|
||||
POWERPC_MMU_620 = POWERPC_MMU_64 | 0x00000002,
|
||||
/* Architecture 2.06 variant */
|
||||
POWERPC_MMU_2_06 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG | 0x00000003,
|
||||
/* Architecture 2.06 "degraded" (no 1T segments) */
|
||||
POWERPC_MMU_2_06 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG
|
||||
| POWERPC_MMU_AMR | 0x00000003,
|
||||
/* Architecture 2.06 "degraded" (no 1T segments or AMR) */
|
||||
POWERPC_MMU_2_06d = POWERPC_MMU_64 | 0x00000003,
|
||||
#endif /* defined(TARGET_PPC64) */
|
||||
};
|
||||
@@ -396,36 +396,12 @@ union ppc_tlb_t {
|
||||
#define SDR_64_HTABSIZE 0x000000000000001FULL
|
||||
#endif /* defined(TARGET_PPC64 */
|
||||
|
||||
#define HASH_PTE_SIZE_32 8
|
||||
#define HASH_PTE_SIZE_64 16
|
||||
|
||||
typedef struct ppc_slb_t ppc_slb_t;
|
||||
struct ppc_slb_t {
|
||||
uint64_t esid;
|
||||
uint64_t vsid;
|
||||
};
|
||||
|
||||
/* Bits in the SLB ESID word */
|
||||
#define SLB_ESID_ESID 0xFFFFFFFFF0000000ULL
|
||||
#define SLB_ESID_V 0x0000000008000000ULL /* valid */
|
||||
|
||||
/* Bits in the SLB VSID word */
|
||||
#define SLB_VSID_SHIFT 12
|
||||
#define SLB_VSID_SHIFT_1T 24
|
||||
#define SLB_VSID_SSIZE_SHIFT 62
|
||||
#define SLB_VSID_B 0xc000000000000000ULL
|
||||
#define SLB_VSID_B_256M 0x0000000000000000ULL
|
||||
#define SLB_VSID_B_1T 0x4000000000000000ULL
|
||||
#define SLB_VSID_VSID 0x3FFFFFFFFFFFF000ULL
|
||||
#define SLB_VSID_PTEM (SLB_VSID_B | SLB_VSID_VSID)
|
||||
#define SLB_VSID_KS 0x0000000000000800ULL
|
||||
#define SLB_VSID_KP 0x0000000000000400ULL
|
||||
#define SLB_VSID_N 0x0000000000000200ULL /* no-execute */
|
||||
#define SLB_VSID_L 0x0000000000000100ULL
|
||||
#define SLB_VSID_C 0x0000000000000080ULL /* class */
|
||||
#define SLB_VSID_LP 0x0000000000000030ULL
|
||||
#define SLB_VSID_ATTR 0x0000000000000FFFULL
|
||||
|
||||
#define SEGMENT_SHIFT_256M 28
|
||||
#define SEGMENT_MASK_256M (~((1ULL << SEGMENT_SHIFT_256M) - 1))
|
||||
|
||||
@@ -965,8 +941,6 @@ struct CPUPPCState {
|
||||
/* MMU context - only relevant for full system emulation */
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
#if defined(TARGET_PPC64)
|
||||
/* Address space register */
|
||||
target_ulong asr;
|
||||
/* PowerPC 64 SLB area */
|
||||
ppc_slb_t slb[64];
|
||||
int slb_nr;
|
||||
@@ -1105,20 +1079,6 @@ do { \
|
||||
env->wdt_period[3] = (d_); \
|
||||
} while (0)
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/* Context used internally during MMU translations */
|
||||
typedef struct mmu_ctx_t mmu_ctx_t;
|
||||
struct mmu_ctx_t {
|
||||
hwaddr raddr; /* Real address */
|
||||
hwaddr eaddr; /* Effective address */
|
||||
int prot; /* Protection bits */
|
||||
hwaddr hash[2]; /* Pagetable hash values */
|
||||
target_ulong ptem; /* Virtual segment ID | API */
|
||||
int key; /* Access key */
|
||||
int nx; /* Non-execute area */
|
||||
};
|
||||
#endif
|
||||
|
||||
#include "cpu-qom.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -1130,17 +1090,14 @@ int cpu_ppc_exec (CPUPPCState *s);
|
||||
is returned if the signal was handled by the virtual CPU. */
|
||||
int cpu_ppc_signal_handler (int host_signum, void *pinfo,
|
||||
void *puc);
|
||||
int cpu_ppc_handle_mmu_fault (CPUPPCState *env, target_ulong address, int rw,
|
||||
int mmu_idx);
|
||||
#define cpu_handle_mmu_fault cpu_ppc_handle_mmu_fault
|
||||
void ppc_hw_interrupt (CPUPPCState *env);
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
int cpu_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
|
||||
int mmu_idx);
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
|
||||
#if defined(TARGET_PPC64)
|
||||
void ppc_store_asr (CPUPPCState *env, target_ulong value);
|
||||
int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
|
||||
#endif /* defined(TARGET_PPC64) */
|
||||
#endif /* !defined(CONFIG_USER_ONLY) */
|
||||
void ppc_store_msr (CPUPPCState *env, target_ulong value);
|
||||
|
||||
@@ -1172,14 +1129,13 @@ void store_40x_dbcr0 (CPUPPCState *env, uint32_t val);
|
||||
void store_40x_sler (CPUPPCState *env, uint32_t val);
|
||||
void store_booke_tcr (CPUPPCState *env, target_ulong val);
|
||||
void store_booke_tsr (CPUPPCState *env, target_ulong val);
|
||||
int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
|
||||
hwaddr *raddrp, target_ulong address,
|
||||
uint32_t pid);
|
||||
void ppc_tlb_invalidate_all (CPUPPCState *env);
|
||||
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask);
|
||||
|
||||
static inline uint64_t ppc_dump_gpr(CPUPPCState *env, int gprn)
|
||||
{
|
||||
uint64_t gprv;
|
||||
@@ -1270,6 +1226,7 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
|
||||
#define SPR_601_UDECR (0x006)
|
||||
#define SPR_LR (0x008)
|
||||
#define SPR_CTR (0x009)
|
||||
#define SPR_UAMR (0x00C)
|
||||
#define SPR_DSCR (0x011)
|
||||
#define SPR_DSISR (0x012)
|
||||
#define SPR_DAR (0x013) /* DAE for PowerPC 601 */
|
||||
@@ -1307,6 +1264,7 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
|
||||
#define SPR_MPC_CMPH (0x09B)
|
||||
#define SPR_MPC_LCTRL1 (0x09C)
|
||||
#define SPR_MPC_LCTRL2 (0x09D)
|
||||
#define SPR_UAMOR (0x09D)
|
||||
#define SPR_MPC_ICTRL (0x09E)
|
||||
#define SPR_MPC_BAR (0x09F)
|
||||
#define SPR_VRSAVE (0x100)
|
||||
@@ -1489,11 +1447,9 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
|
||||
#define SPR_RCPU_MI_RBA2 (0x302)
|
||||
#define SPR_MPC_MI_AP (0x302)
|
||||
#define SPR_PERF3 (0x303)
|
||||
#define SPR_620_PMC1R (0x303)
|
||||
#define SPR_RCPU_MI_RBA3 (0x303)
|
||||
#define SPR_MPC_MI_EPN (0x303)
|
||||
#define SPR_PERF4 (0x304)
|
||||
#define SPR_620_PMC2R (0x304)
|
||||
#define SPR_PERF5 (0x305)
|
||||
#define SPR_MPC_MI_TWC (0x305)
|
||||
#define SPR_PERF6 (0x306)
|
||||
@@ -1509,7 +1465,6 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
|
||||
#define SPR_RCPU_L2U_RBA2 (0x30A)
|
||||
#define SPR_MPC_MD_AP (0x30A)
|
||||
#define SPR_PERFB (0x30B)
|
||||
#define SPR_620_MMCR0R (0x30B)
|
||||
#define SPR_RCPU_L2U_RBA3 (0x30B)
|
||||
#define SPR_MPC_MD_EPN (0x30B)
|
||||
#define SPR_PERFC (0x30C)
|
||||
@@ -1524,9 +1479,7 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
|
||||
#define SPR_UPERF1 (0x311)
|
||||
#define SPR_UPERF2 (0x312)
|
||||
#define SPR_UPERF3 (0x313)
|
||||
#define SPR_620_PMC1W (0x313)
|
||||
#define SPR_UPERF4 (0x314)
|
||||
#define SPR_620_PMC2W (0x314)
|
||||
#define SPR_UPERF5 (0x315)
|
||||
#define SPR_UPERF6 (0x316)
|
||||
#define SPR_UPERF7 (0x317)
|
||||
@@ -1534,7 +1487,6 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
|
||||
#define SPR_UPERF9 (0x319)
|
||||
#define SPR_UPERFA (0x31A)
|
||||
#define SPR_UPERFB (0x31B)
|
||||
#define SPR_620_MMCR0W (0x31B)
|
||||
#define SPR_UPERFC (0x31C)
|
||||
#define SPR_UPERFD (0x31D)
|
||||
#define SPR_UPERFE (0x31E)
|
||||
@@ -1606,49 +1558,33 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
|
||||
#define SPR_USDA (0x3AF)
|
||||
#define SPR_40x_ZPR (0x3B0)
|
||||
#define SPR_BOOKE_MAS7 (0x3B0)
|
||||
#define SPR_620_PMR0 (0x3B0)
|
||||
#define SPR_MMCR2 (0x3B0)
|
||||
#define SPR_PMC5 (0x3B1)
|
||||
#define SPR_40x_PID (0x3B1)
|
||||
#define SPR_620_PMR1 (0x3B1)
|
||||
#define SPR_PMC6 (0x3B2)
|
||||
#define SPR_440_MMUCR (0x3B2)
|
||||
#define SPR_620_PMR2 (0x3B2)
|
||||
#define SPR_4xx_CCR0 (0x3B3)
|
||||
#define SPR_BOOKE_EPLC (0x3B3)
|
||||
#define SPR_620_PMR3 (0x3B3)
|
||||
#define SPR_405_IAC3 (0x3B4)
|
||||
#define SPR_BOOKE_EPSC (0x3B4)
|
||||
#define SPR_620_PMR4 (0x3B4)
|
||||
#define SPR_405_IAC4 (0x3B5)
|
||||
#define SPR_620_PMR5 (0x3B5)
|
||||
#define SPR_405_DVC1 (0x3B6)
|
||||
#define SPR_620_PMR6 (0x3B6)
|
||||
#define SPR_405_DVC2 (0x3B7)
|
||||
#define SPR_620_PMR7 (0x3B7)
|
||||
#define SPR_BAMR (0x3B7)
|
||||
#define SPR_MMCR0 (0x3B8)
|
||||
#define SPR_620_PMR8 (0x3B8)
|
||||
#define SPR_PMC1 (0x3B9)
|
||||
#define SPR_40x_SGR (0x3B9)
|
||||
#define SPR_620_PMR9 (0x3B9)
|
||||
#define SPR_PMC2 (0x3BA)
|
||||
#define SPR_40x_DCWR (0x3BA)
|
||||
#define SPR_620_PMRA (0x3BA)
|
||||
#define SPR_SIAR (0x3BB)
|
||||
#define SPR_405_SLER (0x3BB)
|
||||
#define SPR_620_PMRB (0x3BB)
|
||||
#define SPR_MMCR1 (0x3BC)
|
||||
#define SPR_405_SU0R (0x3BC)
|
||||
#define SPR_620_PMRC (0x3BC)
|
||||
#define SPR_401_SKR (0x3BC)
|
||||
#define SPR_PMC3 (0x3BD)
|
||||
#define SPR_405_DBCR1 (0x3BD)
|
||||
#define SPR_620_PMRD (0x3BD)
|
||||
#define SPR_PMC4 (0x3BE)
|
||||
#define SPR_620_PMRE (0x3BE)
|
||||
#define SPR_SDA (0x3BF)
|
||||
#define SPR_620_PMRF (0x3BF)
|
||||
#define SPR_403_VTBL (0x3CC)
|
||||
#define SPR_403_VTBU (0x3CD)
|
||||
#define SPR_DMISS (0x3D0)
|
||||
@@ -1716,15 +1652,12 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
|
||||
#define SPR_LDSTCR (0x3F8)
|
||||
#define SPR_L2PMCR (0x3F8)
|
||||
#define SPR_750FX_HID2 (0x3F8)
|
||||
#define SPR_620_BUSCSR (0x3F8)
|
||||
#define SPR_Exxx_L1FINV0 (0x3F8)
|
||||
#define SPR_L2CR (0x3F9)
|
||||
#define SPR_620_L2CR (0x3F9)
|
||||
#define SPR_L3CR (0x3FA)
|
||||
#define SPR_750_TDCH (0x3FA)
|
||||
#define SPR_IABR2 (0x3FA)
|
||||
#define SPR_40x_DCCR (0x3FA)
|
||||
#define SPR_620_L2SR (0x3FA)
|
||||
#define SPR_ICTC (0x3FB)
|
||||
#define SPR_40x_ICCR (0x3FB)
|
||||
#define SPR_THRM1 (0x3FC)
|
||||
|
||||
@@ -463,6 +463,11 @@ void helper_store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask)
|
||||
fpscr_set_rounding_mode(env);
|
||||
}
|
||||
|
||||
void store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask)
|
||||
{
|
||||
helper_store_fpscr(env, arg, mask);
|
||||
}
|
||||
|
||||
void helper_float_check_status(CPUPPCState *env)
|
||||
{
|
||||
if (env->exception_index == POWERPC_EXCP_PROGRAM &&
|
||||
|
||||
@@ -382,7 +382,6 @@ DEF_HELPER_1(load_601_rtcl, tl, env)
|
||||
DEF_HELPER_1(load_601_rtcu, tl, env)
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
#if defined(TARGET_PPC64)
|
||||
DEF_HELPER_2(store_asr, void, env, tl)
|
||||
DEF_HELPER_1(load_purr, tl, env)
|
||||
#endif
|
||||
DEF_HELPER_2(store_sdr1, void, env, tl)
|
||||
|
||||
+2
-1
@@ -32,6 +32,7 @@
|
||||
#include "sysemu/device_tree.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/spapr.h"
|
||||
#include "mmu-hash64.h"
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/spapr.h"
|
||||
@@ -1077,7 +1078,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||
dprintf("handle halt\n");
|
||||
ret = kvmppc_handle_halt(cpu);
|
||||
break;
|
||||
#ifdef CONFIG_PSERIES
|
||||
#if defined(TARGET_PPC64)
|
||||
case KVM_EXIT_PAPR_HCALL:
|
||||
dprintf("handle PAPR hypercall\n");
|
||||
run->papr_hcall.ret = spapr_hypercall(cpu,
|
||||
|
||||
@@ -37,7 +37,7 @@ void cpu_save(QEMUFile *f, void *opaque)
|
||||
qemu_put_be32s(f, &fpscr);
|
||||
qemu_put_sbe32s(f, &env->access_type);
|
||||
#if defined(TARGET_PPC64)
|
||||
qemu_put_betls(f, &env->asr);
|
||||
qemu_put_betls(f, &env->spr[SPR_ASR]);
|
||||
qemu_put_sbe32s(f, &env->slb_nr);
|
||||
#endif
|
||||
qemu_put_betls(f, &env->spr[SPR_SDR1]);
|
||||
@@ -125,7 +125,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
|
||||
env->fpscr = fpscr;
|
||||
qemu_get_sbe32s(f, &env->access_type);
|
||||
#if defined(TARGET_PPC64)
|
||||
qemu_get_betls(f, &env->asr);
|
||||
qemu_get_betls(f, &env->spr[SPR_ASR]);
|
||||
qemu_get_sbe32s(f, &env->slb_nr);
|
||||
#endif
|
||||
qemu_get_betls(f, &sdr1);
|
||||
|
||||
@@ -252,41 +252,3 @@ STVE(stvewx, cpu_stl_data, bswap32, u32)
|
||||
|
||||
#undef HI_IDX
|
||||
#undef LO_IDX
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Softmmu support */
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
||||
#define MMUSUFFIX _mmu
|
||||
|
||||
#define SHIFT 0
|
||||
#include "exec/softmmu_template.h"
|
||||
|
||||
#define SHIFT 1
|
||||
#include "exec/softmmu_template.h"
|
||||
|
||||
#define SHIFT 2
|
||||
#include "exec/softmmu_template.h"
|
||||
|
||||
#define SHIFT 3
|
||||
#include "exec/softmmu_template.h"
|
||||
|
||||
/* try to fill the TLB and return an exception if error. If retaddr is
|
||||
NULL, it means that the function was called in C code (i.e. not
|
||||
from generated code or from helper.c) */
|
||||
/* XXX: fix it to restore all registers */
|
||||
void tlb_fill(CPUPPCState *env, target_ulong addr, int is_write, int mmu_idx,
|
||||
uintptr_t retaddr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx);
|
||||
if (unlikely(ret != 0)) {
|
||||
if (likely(retaddr)) {
|
||||
/* now we have a real cpu fault */
|
||||
cpu_restore_state(env, retaddr);
|
||||
}
|
||||
helper_raise_exception_err(env, env->exception_index, env->error_code);
|
||||
}
|
||||
}
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
@@ -35,12 +35,6 @@ void helper_store_dump_spr(CPUPPCState *env, uint32_t sprn)
|
||||
env->spr[sprn]);
|
||||
}
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
#if defined(TARGET_PPC64)
|
||||
void helper_store_asr(CPUPPCState *env, target_ulong val)
|
||||
{
|
||||
ppc_store_asr(env, val);
|
||||
}
|
||||
#endif
|
||||
|
||||
void helper_store_sdr1(CPUPPCState *env, target_ulong val)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,102 @@
|
||||
#if !defined (__MMU_HASH32_H__)
|
||||
#define __MMU_HASH32_H__
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash);
|
||||
hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong addr);
|
||||
int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
|
||||
int mmu_idx);
|
||||
|
||||
/*
|
||||
* Segment register definitions
|
||||
*/
|
||||
|
||||
#define SR32_T 0x80000000
|
||||
#define SR32_KS 0x40000000
|
||||
#define SR32_KP 0x20000000
|
||||
#define SR32_NX 0x10000000
|
||||
#define SR32_VSID 0x00ffffff
|
||||
|
||||
/*
|
||||
* Block Address Translation (BAT) definitions
|
||||
*/
|
||||
|
||||
#define BATU32_BEPI 0xfffe0000
|
||||
#define BATU32_BL 0x00001ffc
|
||||
#define BATU32_VS 0x00000002
|
||||
#define BATU32_VP 0x00000001
|
||||
|
||||
|
||||
#define BATL32_BRPN 0xfffe0000
|
||||
#define BATL32_WIMG 0x00000078
|
||||
#define BATL32_PP 0x00000003
|
||||
|
||||
/* PowerPC 601 has slightly different BAT registers */
|
||||
|
||||
#define BATU32_601_KS 0x00000008
|
||||
#define BATU32_601_KP 0x00000004
|
||||
#define BATU32_601_PP 0x00000003
|
||||
|
||||
#define BATL32_601_V 0x00000040
|
||||
#define BATL32_601_BL 0x0000003f
|
||||
|
||||
/*
|
||||
* Hash page table definitions
|
||||
*/
|
||||
|
||||
#define HPTES_PER_GROUP 8
|
||||
#define HASH_PTE_SIZE_32 8
|
||||
#define HASH_PTEG_SIZE_32 (HASH_PTE_SIZE_32 * HPTES_PER_GROUP)
|
||||
|
||||
#define HPTE32_V_VALID 0x80000000
|
||||
#define HPTE32_V_VSID 0x7fffff80
|
||||
#define HPTE32_V_SECONDARY 0x00000040
|
||||
#define HPTE32_V_API 0x0000003f
|
||||
#define HPTE32_V_COMPARE(x, y) (!(((x) ^ (y)) & 0x7fffffbf))
|
||||
|
||||
#define HPTE32_R_RPN 0xfffff000
|
||||
#define HPTE32_R_R 0x00000100
|
||||
#define HPTE32_R_C 0x00000080
|
||||
#define HPTE32_R_W 0x00000040
|
||||
#define HPTE32_R_I 0x00000020
|
||||
#define HPTE32_R_M 0x00000010
|
||||
#define HPTE32_R_G 0x00000008
|
||||
#define HPTE32_R_WIMG 0x00000078
|
||||
#define HPTE32_R_PP 0x00000003
|
||||
|
||||
static inline target_ulong ppc_hash32_load_hpte0(CPUPPCState *env,
|
||||
hwaddr pte_offset)
|
||||
{
|
||||
assert(!env->external_htab); /* Not supported on 32-bit for now */
|
||||
return ldl_phys(env->htab_base + pte_offset);
|
||||
}
|
||||
|
||||
static inline target_ulong ppc_hash32_load_hpte1(CPUPPCState *env,
|
||||
hwaddr pte_offset)
|
||||
{
|
||||
assert(!env->external_htab); /* Not supported on 32-bit for now */
|
||||
return ldl_phys(env->htab_base + pte_offset + HASH_PTE_SIZE_32/2);
|
||||
}
|
||||
|
||||
static inline void ppc_hash32_store_hpte0(CPUPPCState *env,
|
||||
hwaddr pte_offset, target_ulong pte0)
|
||||
{
|
||||
assert(!env->external_htab); /* Not supported on 32-bit for now */
|
||||
stl_phys(env->htab_base + pte_offset, pte0);
|
||||
}
|
||||
|
||||
static inline void ppc_hash32_store_hpte1(CPUPPCState *env,
|
||||
hwaddr pte_offset, target_ulong pte1)
|
||||
{
|
||||
assert(!env->external_htab); /* Not supported on 32-bit for now */
|
||||
stl_phys(env->htab_base + pte_offset + HASH_PTE_SIZE_32/2, pte1);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint32_t pte0, pte1;
|
||||
} ppc_hash_pte32_t;
|
||||
|
||||
#endif /* CONFIG_USER_ONLY */
|
||||
|
||||
#endif /* __MMU_HASH32_H__ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user