On Tue, Mar 13, 2012 at 4:47 AM, Peter Maydell <peter.maydell at linaro.org> wrote: > On 13 March 2012 00:18, Rusty Russell <rusty at rustcorp.com.au> wrote: >> + ? ? ? MCR(p15, 1, ANY, 9, 0, 2, ignore_write, 0), >> + ? ? ? MRC(p15, 1, ANY, 9, 0, 2, read_l2ctlr, 0), > > Hmm. I'm generally a bit suspicious of anything that doesn't > explicitly say which are crn/crm/op1/op2, because the various > docs and tables in TRMs and manuals have no particular > consistency about ordering and it's fantastically easy to get > confused. However the MRC()/MCR() are quite cute. > > Are you going to want to encode "this is how this cp15 register > is reset" in your tables at some point? Or "r/o for user mode > but r/w for kernel" or other complicated permissions? One > downside of these macros is that you've lost the ability to > use named fields in the struct initialisers and are back to > a plain list, which is fine when there are only 2 things other > than the crn/crm/op1/op2 but might get ugly if we need to add > more later. > the version in the v7 patch series does seem to address both items (take a look at the snippet below), but it's a define mess. Let me know what you think there. +#define DF (-1UL) /* Default: If nothing else fits, use this one */ +#define CRn(_x) .CRn = _x +#define CRm(_x) .CRm = _x +#define Op1(_x) .Op1 = _x +#define Op2(_x) .Op2 = _x +#define is64 .is_64 = true +#define is32 .is_64 = false +#define READ .is_w = false +#define WRITE .is_w = true +#define RW .is_w = DF + +static const struct coproc_emulate coproc_emulate[] = { + /* + * L2CTLR access: + * + * Ignore writes completely. + * + * FIXME: Hack Alert: Read zero as default case. + */ + { CRn( 9), CRm( 0), Op1( 1), Op2( 2), is32, WRITE, ignore_write}, + { CRn( 9), CRm( 0), Op1( 1), Op2( 2), is32, READ, read_l2ctlr}, + { CRn( 9), CRm(DF), Op1(DF), Op2(DF), is32, WRITE, ignore_write}, + { CRn( 9), CRm(DF), Op1(DF), Op2(DF), is32, READ, read_zero}, + + /* + * These CRn == 10 entries may not need to exist - if we can + * ignore guest attempts to tamper with TLB lockdowns then it + * should be enough to store/restore the host/guest PRRR and + * NMRR memory remap registers and allow guest direct access + * to these registers. + * + * TLB Lockdown operations - ignored + */ + { CRn(10), CRm( 0), Op1(DF), Op2(DF), is32, WRITE, ignore_write}, + { CRn(10), CRm( 2), Op1( 0), Op2( 0), is32, RW, access_cp15_reg, + c10_PRRR}, + { CRn(10), CRm( 2), Op1( 0), Op2( 1), is32, RW, access_cp15_reg, + c10_NMRR}, + + /* + * The CP15 c15 register is architecturally implementation + * defined, but some guest kernels attempt to read/write a + * diagnostics register here. We always return 0 and ignore + * writes and hope for the best. + */ + { CRn(15), CRm(DF), Op1(DF), Op2(DF), is32, WRITE, ignore_write, 1}, + { CRn(15), CRm(DF), Op1(DF), Op2(DF), is32, READ, read_zero, 1}, +}; + +#undef is64 +#undef is32 +#undef READ +#undef WRITE +#undef RW -Christoffer