From: qemu@gibson.dropbear.id.au
To: qemu-devel@nongnu.org
Cc: paulus@samba.org, agraf@suse.de, anton@samba.org
Subject: [Qemu-devel] [PATCH 02/28] Clean up PowerPC SLB handling code
Date: Tue, 15 Feb 2011 15:56:13 +1100 [thread overview]
Message-ID: <1297745799-26148-3-git-send-email-qemu@gibson.dropbear.id.au> (raw)
In-Reply-To: <1297745799-26148-1-git-send-email-qemu@gibson.dropbear.id.au>
From: David Gibson <david@gibson.dropbear.id.au>
Currently the SLB information when emulating a PowerPC 970 is
storeed in a structure with the unhelpfully named fields 'tmp'
and 'tmp64'. While the layout in these fields does match the
description of the SLB in the architecture document, it is not
convenient either for looking up the SLB, or for emulating the
slbmte instruction.
This patch, therefore, reorganizes the SLB entry structure to be
divided in the the "ESID related" and "VSID related" fields as
they are divided in instructions accessing the SLB.
In addition to making the code smaller and more readable, this will
make it easier to implement for the 1TB segments used in more
recent PowerPC chips.
Signed-off-by: David Gibson <dwg@au1.ibm.com>
---
target-ppc/cpu.h | 29 +++++++-
target-ppc/helper.c | 178 ++++++++++++++----------------------------------
target-ppc/helper.h | 1 -
target-ppc/op_helper.c | 9 +--
4 files changed, 80 insertions(+), 137 deletions(-)
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index deb8d7c..a20c132 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -43,6 +43,8 @@
# define TARGET_VIRT_ADDR_SPACE_BITS 64
#endif
+#define TARGET_PAGE_BITS_16M 24
+
#else /* defined (TARGET_PPC64) */
/* PowerPC 32 definitions */
#define TARGET_LONG_BITS 32
@@ -359,10 +361,31 @@ union ppc_tlb_t {
typedef struct ppc_slb_t ppc_slb_t;
struct ppc_slb_t {
- uint64_t tmp64;
- uint32_t tmp;
+ 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_SSIZE_SHIFT 62
+#define SLB_VSID_B 0xc000000000000000ULL
+#define SLB_VSID_B_256M 0x0000000000000000ULL
+#define SLB_VSID_VSID 0x3FFFFFFFFFFFF000ULL
+#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)
+
/*****************************************************************************/
/* Machine state register bits definition */
#define MSR_SF 63 /* Sixty-four-bit mode hflags */
@@ -755,7 +778,7 @@ void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
void ppc_store_asr (CPUPPCState *env, target_ulong value);
target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr);
target_ulong ppc_load_sr (CPUPPCState *env, int sr_nr);
-void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
+int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
#endif /* defined(TARGET_PPC64) */
void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value);
#endif /* !defined(CONFIG_USER_ONLY) */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 4b49101..2094ca3 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -672,85 +672,36 @@ static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
}
#if defined(TARGET_PPC64)
-static ppc_slb_t *slb_get_entry(CPUPPCState *env, int nr)
-{
- ppc_slb_t *retval = &env->slb[nr];
-
-#if 0 // XXX implement bridge mode?
- if (env->spr[SPR_ASR] & 1) {
- target_phys_addr_t sr_base;
-
- sr_base = env->spr[SPR_ASR] & 0xfffffffffffff000;
- sr_base += (12 * nr);
-
- retval->tmp64 = ldq_phys(sr_base);
- retval->tmp = ldl_phys(sr_base + 8);
- }
-#endif
-
- return retval;
-}
-
-static void slb_set_entry(CPUPPCState *env, int nr, ppc_slb_t *slb)
-{
- ppc_slb_t *entry = &env->slb[nr];
-
- if (slb == entry)
- return;
-
- entry->tmp64 = slb->tmp64;
- entry->tmp = slb->tmp;
-}
-
-static inline int slb_is_valid(ppc_slb_t *slb)
-{
- return (int)(slb->tmp64 & 0x0000000008000000ULL);
-}
-
-static inline void slb_invalidate(ppc_slb_t *slb)
-{
- slb->tmp64 &= ~0x0000000008000000ULL;
-}
-
static inline int slb_lookup(CPUPPCState *env, target_ulong eaddr,
target_ulong *vsid, target_ulong *page_mask,
int *attr, int *target_page_bits)
{
- target_ulong mask;
- int n, ret;
+ uint64_t esid;
+ int n;
- ret = -5;
LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
- mask = 0x0000000000000000ULL; /* Avoid gcc warning */
+
+ esid = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
+
for (n = 0; n < env->slb_nr; n++) {
- ppc_slb_t *slb = slb_get_entry(env, n);
-
- LOG_SLB("%s: seg %d %016" PRIx64 " %08"
- PRIx32 "\n", __func__, n, slb->tmp64, slb->tmp);
- if (slb_is_valid(slb)) {
- /* SLB entry is valid */
- mask = 0xFFFFFFFFF0000000ULL;
- if (slb->tmp & 0x8) {
- /* 16 MB PTEs */
- if (target_page_bits)
- *target_page_bits = 24;
- } else {
- /* 4 KB PTEs */
- if (target_page_bits)
- *target_page_bits = TARGET_PAGE_BITS;
- }
- if ((eaddr & mask) == (slb->tmp64 & mask)) {
- /* SLB match */
- *vsid = ((slb->tmp64 << 24) | (slb->tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
- *page_mask = ~mask;
- *attr = slb->tmp & 0xFF;
- ret = n;
- break;
+ ppc_slb_t *slb = &env->slb[n];
+
+ LOG_SLB("%s: slot %d %016" PRIx64 " %016"
+ PRIx64 "\n", __func__, n, slb->esid, slb->vsid);
+ if (slb->esid == esid) {
+ *vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
+ *page_mask = ~SEGMENT_MASK_256M;
+ *attr = slb->vsid & SLB_VSID_ATTR;
+ if (target_page_bits) {
+ *target_page_bits = (slb->vsid & SLB_VSID_L)
+ ? TARGET_PAGE_BITS_16M
+ : TARGET_PAGE_BITS;
}
+ return n;
}
}
- return ret;
+ return -5;
}
void ppc_slb_invalidate_all (CPUPPCState *env)
@@ -760,11 +711,10 @@ void ppc_slb_invalidate_all (CPUPPCState *env)
do_invalidate = 0;
/* XXX: Warning: slbia never invalidates the first segment */
for (n = 1; n < env->slb_nr; n++) {
- ppc_slb_t *slb = slb_get_entry(env, n);
+ ppc_slb_t *slb = &env->slb[n];
- if (slb_is_valid(slb)) {
- slb_invalidate(slb);
- slb_set_entry(env, n, slb);
+ if (slb->esid & SLB_ESID_V) {
+ slb->esid &= ~SLB_ESID_V;
/* XXX: given the fact that segment size is 256 MB or 1TB,
* and we still don't have a tlb_flush_mask(env, n, mask)
* in Qemu, we just invalidate all TLBs
@@ -781,68 +731,44 @@ void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
target_ulong vsid, page_mask;
int attr;
int n;
+ ppc_slb_t *slb;
n = slb_lookup(env, T0, &vsid, &page_mask, &attr, NULL);
- if (n >= 0) {
- ppc_slb_t *slb = slb_get_entry(env, n);
-
- if (slb_is_valid(slb)) {
- slb_invalidate(slb);
- slb_set_entry(env, n, slb);
- /* XXX: given the fact that segment size is 256 MB or 1TB,
- * and we still don't have a tlb_flush_mask(env, n, mask)
- * in Qemu, we just invalidate all TLBs
- */
- tlb_flush(env, 1);
- }
+ if (n < 0) {
+ return;
}
-}
-target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
-{
- target_ulong rt;
- ppc_slb_t *slb = slb_get_entry(env, slb_nr);
+ slb = &env->slb[n];
- if (slb_is_valid(slb)) {
- /* SLB entry is valid */
- /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */
- rt = slb->tmp >> 8; /* 65:88 => 40:63 */
- rt |= (slb->tmp64 & 0x7) << 24; /* 62:64 => 37:39 */
- /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */
- rt |= ((slb->tmp >> 4) & 0xF) << 27;
- } else {
- rt = 0;
- }
- LOG_SLB("%s: %016" PRIx64 " %08" PRIx32 " => %d "
- TARGET_FMT_lx "\n", __func__, slb->tmp64, slb->tmp, slb_nr, rt);
+ if (slb->esid & SLB_ESID_V) {
+ slb->esid &= ~SLB_ESID_V;
- return rt;
+ /* XXX: given the fact that segment size is 256 MB or 1TB,
+ * and we still don't have a tlb_flush_mask(env, n, mask)
+ * in Qemu, we just invalidate all TLBs
+ */
+ tlb_flush(env, 1);
+ }
}
-void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
+int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
{
- ppc_slb_t *slb;
-
- uint64_t vsid;
- uint64_t esid;
- int flags, valid, slb_nr;
-
- vsid = rs >> 12;
- flags = ((rs >> 8) & 0xf);
+ int slot = rb & 0xfff;
+ uint64_t esid = rb & ~0xfff;
+ ppc_slb_t *slb = &env->slb[slot];
- esid = rb >> 28;
- valid = (rb & (1 << 27));
- slb_nr = rb & 0xfff;
+ if (slot >= env->slb_nr) {
+ return -1;
+ }
- slb = slb_get_entry(env, slb_nr);
- slb->tmp64 = (esid << 28) | valid | (vsid >> 24);
- slb->tmp = (vsid << 8) | (flags << 3);
+ slb->esid = esid;
+ slb->vsid = rs;
LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" PRIx64
- " %08" PRIx32 "\n", __func__, slb_nr, rb, rs, slb->tmp64,
- slb->tmp);
+ " %016" PRIx64 "\n", __func__, slot, rb, rs,
+ slb->esid, slb->vsid);
- slb_set_entry(env, slb_nr, slb);
+ return 0;
}
#endif /* defined(TARGET_PPC64) */
@@ -860,24 +786,22 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
{
target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;
target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
-#if defined(TARGET_PPC64)
- int attr;
-#endif
int ds, vsid_sh, sdr_sh, pr, target_page_bits;
int ret, ret2;
pr = msr_pr;
#if defined(TARGET_PPC64)
if (env->mmu_model & POWERPC_MMU_64) {
+ int attr;
+
LOG_MMU("Check SLBs\n");
ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr,
&target_page_bits);
if (ret < 0)
return ret;
- ctx->key = ((attr & 0x40) && (pr != 0)) ||
- ((attr & 0x80) && (pr == 0)) ? 1 : 0;
+ ctx->key = !!(pr ? (attr & SLB_VSID_KP) : (attr & SLB_VSID_KS));
ds = 0;
- ctx->nx = attr & 0x10 ? 1 : 0;
+ ctx->nx = !!(attr & SLB_VSID_N);
ctx->eaddr = eaddr;
vsid_mask = 0x00003FFFFFFFFF80ULL;
vsid_sh = 7;
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 2bf9283..d512cb0 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -340,7 +340,6 @@ DEF_HELPER_1(74xx_tlbi, void, tl)
DEF_HELPER_FLAGS_0(tlbia, TCG_CALL_CONST, void)
DEF_HELPER_FLAGS_1(tlbie, TCG_CALL_CONST, void, tl)
#if defined(TARGET_PPC64)
-DEF_HELPER_FLAGS_1(load_slb, TCG_CALL_CONST, tl, tl)
DEF_HELPER_FLAGS_2(store_slb, TCG_CALL_CONST, void, tl, tl)
DEF_HELPER_FLAGS_0(slbia, TCG_CALL_CONST, void)
DEF_HELPER_FLAGS_1(slbie, TCG_CALL_CONST, void, tl)
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 17e070a..bf41627 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -3746,14 +3746,11 @@ void helper_store_sr (target_ulong sr_num, target_ulong val)
/* SLB management */
#if defined(TARGET_PPC64)
-target_ulong helper_load_slb (target_ulong slb_nr)
-{
- return ppc_load_slb(env, slb_nr);
-}
-
void helper_store_slb (target_ulong rb, target_ulong rs)
{
- ppc_store_slb(env, rb, rs);
+ if (ppc_store_slb(env, rb, rs) < 0) {
+ helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL);
+ }
}
void helper_slbia (void)
--
1.7.1
next prev parent reply other threads:[~2011-02-15 4:57 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-02-15 4:56 [Qemu-devel] RFC: Implement emulation of pSeries logical partitions (v2) qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 01/28] Add TAGS and *~ to .gitignore qemu
2011-02-15 4:56 ` qemu [this message]
2011-02-15 4:56 ` [Qemu-devel] [PATCH 03/28] Allow qemu_devtree_setprop() to take arbitrary values qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 04/28] Add a hook to allow hypercalls to be emulated on PowerPC qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 05/28] Implement PowerPC slbmfee and slbmfev instructions qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 06/28] Implement missing parts of the logic for the POWER PURR qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 07/28] Correct ppc popcntb logic, implement popcntw and popcntd qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 08/28] Clean up slb_lookup() function qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 09/28] Parse SDR1 on mtspr instead of at translate time qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 10/28] Use "hash" more consistently in ppc mmu code qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 11/28] Better factor the ppc hash translation path qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 12/28] Support 1T segments on ppc qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 13/28] Add POWER7 support for ppc qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 14/28] Start implementing pSeries logical partition machine qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 15/28] Implement the bus structure for PAPR virtual IO qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 16/28] Virtual hash page table handling on pSeries machine qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 17/28] Implement hcall based RTAS for pSeries machines qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 18/28] Implement assorted pSeries hcalls and RTAS methods qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 19/28] Implement the PAPR (pSeries) virtualized interrupt controller (xics) qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 20/28] Add PAPR H_VIO_SIGNAL hypercall and infrastructure for VIO interrupts qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 21/28] Add (virtual)_interrupt to PAPR virtual tty device qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 22/28] Implement TCE translation for sPAPR VIO qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 23/28] Implement sPAPR Virtual LAN (ibmveth) qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 24/28] Implement PAPR CRQ hypercalls qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 25/28] Implement PAPR virtual SCSI interface (ibmvscsi) qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 26/28] Add a PAPR TCE-bypass mechanism for the pSeries machine qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 27/28] Add SLOF-based partition firmware for pSeries machine, allowing more boot options qemu
2011-02-15 4:56 ` [Qemu-devel] [PATCH 28/28] Implement PAPR VPA functions for pSeries shared processor partitions qemu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1297745799-26148-3-git-send-email-qemu@gibson.dropbear.id.au \
--to=qemu@gibson.dropbear.id.au \
--cc=agraf@suse.de \
--cc=anton@samba.org \
--cc=paulus@samba.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).