/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that 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, write to the Free Software * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Copyright (C) IBM Corp. 2005 * * Authors: Jimi Xenidis */ #include #include #include #include #include #include "mpic_init.h" #include "oftree.h" #include "of-devtree.h" #undef DEBUG #define CONFIG_SHARE_MPIC #ifdef DEBUG #define DBG(fmt...) printk(fmt) #else #define DBG(fmt...) #endif #define PANIC(fmt...) DBG(fmt) static struct mpic *mpic; static unsigned long opic_addr; static unsigned int opic_flags; /* * from OF_IEEE_1275 * * pg 175, property "ranges" * * The number of integers in each size entry is determined by the * value of the #size-cells property of this node (the node in which * the ranges property appears) or 1 if the #size-cells property is * absent. * * * pg 177, property "reg" * * The number of integers in each size entry is determined by the * value of the "#size-cells" property in the parent node. If the * parent node has no such property, the value is one. */ static unsigned long reg2(void *oft_p, ofdn_t c) { int rc; /* the struct isa_reg_property is for a value of 2 for * #address-cells and a value of 1 for #size-cells (of the * parent). */ struct isa_reg_property { u32 space; u32 address; u32 size; } isa_reg; rc = ofd_getprop(oft_p, c, "reg", &isa_reg, sizeof(isa_reg)); DBG("%s: reg property address=0x%08x size=0x%08x\n", __func__, isa_reg.address, isa_reg.size); return isa_reg.address; } static unsigned long reg1(void *oft_p, ofdn_t c) { int rc; /* the struct reg_property32 is for a value of 1 for * #address-cells and a value of 1 for #size-cells. */ struct reg_property32 { u32 address; u32 size; } reg; rc = ofd_getprop(oft_p, c, "reg", ®, sizeof(reg)); DBG("%s: reg property address=0x%08x size=0x%08x\n", __func__, reg.address, reg.size); return reg.address; } static unsigned long find_reg_addr_from_node(void *oft_p, ofdn_t c) { int p_len; unsigned long reg_addr = 0; u32 size_c = 1; u32 addr_c = 2; ofdn_t parent; if (c == OFD_ROOT) { parent = c; } else { parent = ofd_node_parent(oft_p, c); } p_len = ofd_getprop(oft_p, parent, "#size-cells", &size_c, sizeof(size_c)); DBG("%s size is %d\n", __func__, size_c); p_len = ofd_getprop(oft_p, parent, "#address-cells", &addr_c, sizeof(addr_c)); DBG("%s address is %d\n", __func__, addr_c); if ( 1 != size_c ) { PANIC("Unsupported size for reg property\n"); } if ( 1 == addr_c) { reg_addr = reg1(oft_p, c); } else if ( 2 == addr_c ) { reg_addr = reg2(oft_p, c); } else { PANIC("Unsupported address size for reg property\n"); } DBG("%s: address 0x%lx\n", __func__, reg_addr); return reg_addr; } /* * from OF_IEEE_1275 * * pg 175, property "ranges" * * The ranges property value is a sequence of child-phys parent-phys * size specifications. Child-phys is an address, encoded as with * encode-phys, in the child address space. Parent-phys is an address * (likewise encoded as with encode-phys) in the parent address * space. Size is a list of integers, each encoded as with encode-int, * denoting the length of the child's address range. */ static unsigned long find_ranges_addr_from_node(void *oft_p, ofdn_t c) { unsigned long ranges_addr = 0; int ranges_i; ofdn_t parent; u32 addr_c = 2; u32 ranges[64]; int p_len; parent = ofd_node_parent(oft_p, c); parent = ofd_node_parent(oft_p, parent); p_len = ofd_getprop(oft_p, parent, "ranges", &ranges, sizeof(ranges)); DBG("%s: ranges\n", __func__); int i; for (i=0; i= 0) { DBG("%s: Big Endian found\n", __func__); flags |= MPIC_BIG_ENDIAN; } DBG("%s: flags 0x%x\n", __func__, flags); return flags; } static int find_mpic_simple_probe(void *oft_p) { u32 addr_cells; int rc; u32 addr[2]; rc = ofd_getprop(oft_p, OFD_ROOT, "#address-cells", &addr_cells, sizeof(addr_cells)); if ( rc < 0 ) { /* if the property does not exist use its default value, 2 */ addr_cells = 2; } rc = ofd_getprop(oft_p, OFD_ROOT, "platform-open-pic", addr, sizeof(addr)); if (rc < 0) { return rc; } opic_addr = addr[0]; if (addr_cells == 2) { opic_addr <<= 32; opic_addr |= addr[1]; } DBG("%s: found OpenPIC at: 0x%lx\n", __func__, opic_addr); /* we did not really find the pic device, only its address. * We use big endian and broken u3 by default. */ opic_flags |= MPIC_BIG_ENDIAN | MPIC_BROKEN_U3; return 0; } static int find_mpic_canonical_probe(void *oft_p) { ofdn_t c; const char mpic_type[] = "open-pic"; /* some paths are special and we cannot find the address * by the usual method */ const char *excluded_paths[] = { "/interrupt-controller" }; /* * Search through the OFD tree for all devices of type 'open_pic'. * We select the one without an 'interrupt' property. */ c = ofd_node_find_by_prop(oft_p, OFD_ROOT, "device_type", mpic_type, sizeof(mpic_type)); while (c > 0) { int int_len; int good_mpic; const char * path = ofd_node_path(oft_p, c); good_mpic = 0; int_len = ofd_getprop(oft_p, c, "interrupts", NULL, 0); if (int_len < 0) { int i; /* there is no property interrupt. This could be the pic */ DBG("%s: potential OpenPIC in: %s\n", __func__, path); good_mpic = 1; for (i = 0; i < ARRAY_SIZE(excluded_paths) && good_mpic; i++) { const char *excluded_path = excluded_paths[i]; if (!strncmp(path, excluded_path, strlen(excluded_path))) good_mpic = 0; } } if (good_mpic) { DBG("%s: found OpenPIC in: %s\n", __func__, path); opic_addr = find_pic_address_from_node(oft_p, c); opic_flags = find_pic_flags_from_node(oft_p, c); return 0; } c = ofd_node_find_next(oft_p, c); } DBG("%s: Could not find a pic\n", __func__); return -1; } static int find_mpic(void) { void *oft_p; int rc; opic_addr = (unsigned long)-1; opic_flags = 0; oft_p = (void *)oftree; rc = find_mpic_simple_probe(oft_p); if (rc < 0) { DBG("%s: Searching for pic ...\n", __func__); rc = find_mpic_canonical_probe(oft_p); } return rc; } #ifdef CONFIG_SHARE_MPIC static struct hw_interrupt_type hc_irq; static struct hw_interrupt_type *share_mpic( struct hw_interrupt_type *mpic_irq, struct hw_interrupt_type *xen_irq) { hc_irq.startup = mpic_irq->startup; mpic_irq->startup = xen_irq->startup; hc_irq.enable = mpic_irq->enable; mpic_irq->enable = xen_irq->enable; hc_irq.disable = mpic_irq->disable; mpic_irq->disable = xen_irq->disable; hc_irq.shutdown = mpic_irq->shutdown; mpic_irq->shutdown = xen_irq->shutdown; hc_irq.ack = mpic_irq->ack; mpic_irq->ack = xen_irq->ack; hc_irq.end = mpic_irq->end; mpic_irq->end = xen_irq->end; hc_irq.set_affinity = mpic_irq->set_affinity; mpic_irq->set_affinity = xen_irq->set_affinity; return &hc_irq; } #else /* CONFIG_SHARE_MPIC */ #define share_mpic(M,X) (M) #endif static unsigned int mpic_startup_ipi(unsigned int irq) { mpic->hc_ipi.enable(irq); return 0; } int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct cpu_user_regs *), unsigned long irqflags, const char * devname, void *dev_id) { int retval; struct irqaction *action; void (*func)(int, void *, struct cpu_user_regs *); action = xmalloc(struct irqaction); if (!action) { BUG(); return -ENOMEM; } /* Xen's handler prototype is slightly different than Linux's. */ func = (void (*)(int, void *, struct cpu_user_regs *))handler; action->handler = func; action->name = devname; action->dev_id = dev_id; retval = setup_irq(irq, action); if (retval) { BUG(); xfree(action); } return retval; } struct hw_interrupt_type *xen_mpic_init(struct hw_interrupt_type *xen_irq) { unsigned int isu_size; unsigned int irq_offset; unsigned int irq_count; unsigned int ipi_offset; unsigned char *senses; unsigned int senses_count; struct hw_interrupt_type *hit; printk("%s: start\n", __func__); io_apic_irqs = ~0; /* all IRQs go through IOAPIC */ irq_vector[0] = FIRST_DEVICE_VECTOR; vector_irq[FIRST_DEVICE_VECTOR] = 0; isu_size = 0; irq_offset = 0; irq_count = 128; ipi_offset = 128; senses = NULL; senses_count = 0; if (find_mpic()) { printk("%s: ERROR: Could not find open pic.\n", __func__); return NULL; } mpic = mpic_alloc(opic_addr, opic_flags | MPIC_PRIMARY | MPIC_WANTS_RESET, isu_size, irq_offset, irq_count, ipi_offset, senses, senses_count, "Xen-U3-MPIC"); BUG_ON(mpic == NULL); mpic_init(mpic); hit = share_mpic(&mpic->hc_irq, xen_irq); printk("%s: success\n", __func__); mpic->hc_ipi.ack = xen_irq->ack; mpic->hc_ipi.startup = mpic_startup_ipi; mpic_request_ipis(); return hit; } int xen_mpic_get_irq(struct cpu_user_regs *regs) { BUG_ON(mpic == NULL); return mpic_get_one_irq(mpic, regs); } 7'>247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
--- a/src/lvm.c
+++ b/src/lvm.c
@@ -31,6 +31,9 @@
 /* limit for table tag-method chains (to avoid loops) */
 #define MAXTAGLOOP	100
 
+#ifdef __GNUC__
+#define COMPUTED_GOTO 1
+#endif
 
 /*
  * If 'obj' is a string, it is tried to be interpreted as a number.
@@ -564,12 +567,63 @@
     ARITH_OP1_END
 #endif
 
+#ifdef COMPUTED_GOTO
+#define OPCODE_TARGET(op) DO_OP_##op:
+#define CALL_OPCODE(op) goto *opcodes[op];
+#define OPCODE_PTR(op) [OP_##op] = &&DO_OP_##op
+#else
+#define OPCODE_TARGET(op) case OP_##op:
+#define CALL_OPCODE(op) switch (op)
+#endif
+
 
 void luaV_execute (lua_State *L, int nexeccalls) {
   LClosure *cl;
   StkId base;
   TValue *k;
   const Instruction *pc;
+#ifdef COMPUTED_GOTO
+  static const void *opcodes[] = {
+   OPCODE_PTR(MOVE),
+   OPCODE_PTR(LOADK),
+   OPCODE_PTR(LOADBOOL),
+   OPCODE_PTR(LOADNIL),
+   OPCODE_PTR(GETUPVAL),
+   OPCODE_PTR(GETGLOBAL),
+   OPCODE_PTR(GETTABLE),
+   OPCODE_PTR(SETGLOBAL),
+   OPCODE_PTR(SETUPVAL),
+   OPCODE_PTR(SETTABLE),
+   OPCODE_PTR(NEWTABLE),
+   OPCODE_PTR(SELF),
+   OPCODE_PTR(ADD),
+   OPCODE_PTR(SUB),
+   OPCODE_PTR(MUL),
+   OPCODE_PTR(DIV),
+   OPCODE_PTR(MOD),
+   OPCODE_PTR(POW),
+   OPCODE_PTR(UNM),
+   OPCODE_PTR(NOT),
+   OPCODE_PTR(LEN),
+   OPCODE_PTR(CONCAT),
+   OPCODE_PTR(JMP),
+   OPCODE_PTR(EQ),
+   OPCODE_PTR(LT),
+   OPCODE_PTR(LE),
+   OPCODE_PTR(TEST),
+   OPCODE_PTR(TESTSET),
+   OPCODE_PTR(CALL),
+   OPCODE_PTR(TAILCALL),
+   OPCODE_PTR(RETURN),
+   OPCODE_PTR(FORLOOP),
+   OPCODE_PTR(FORPREP),
+   OPCODE_PTR(TFORLOOP),
+   OPCODE_PTR(SETLIST),
+   OPCODE_PTR(CLOSE),
+   OPCODE_PTR(CLOSURE),
+   OPCODE_PTR(VARARG)
+  };
+#endif
  reentry:  /* entry point */
   lua_assert(isLua(L->ci));
   pc = L->savedpc;
@@ -594,33 +648,33 @@
     lua_assert(base == L->base && L->base == L->ci->base);
     lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
     lua_assert(L->top == L->ci->top || luaG_checkopenop(i));
-    switch (GET_OPCODE(i)) {
-      case OP_MOVE: {
+    CALL_OPCODE(GET_OPCODE(i)) {
+      OPCODE_TARGET(MOVE) {
         setobjs2s(L, ra, RB(i));
         continue;
       }
-      case OP_LOADK: {
+      OPCODE_TARGET(LOADK) {
         setobj2s(L, ra, KBx(i));
         continue;
       }
-      case OP_LOADBOOL: {
+      OPCODE_TARGET(LOADBOOL) {
         setbvalue(ra, GETARG_B(i));
         if (GETARG_C(i)) pc++;  /* skip next instruction (if C) */
         continue;
       }
-      case OP_LOADNIL: {
+      OPCODE_TARGET(LOADNIL) {
         TValue *rb = RB(i);
         do {
           setnilvalue(rb--);
         } while (rb >= ra);
         continue;
       }
-      case OP_GETUPVAL: {
+      OPCODE_TARGET(GETUPVAL) {
         int b = GETARG_B(i);
         setobj2s(L, ra, cl->upvals[b]->v);
         continue;
       }
-      case OP_GETGLOBAL: {
+      OPCODE_TARGET(GETGLOBAL) {
         TValue g;
         TValue *rb = KBx(i);
         sethvalue(L, &g, cl->env);
@@ -628,88 +682,88 @@
         Protect(luaV_gettable(L, &g, rb, ra));
         continue;
       }
-      case OP_GETTABLE: {
+      OPCODE_TARGET(GETTABLE) {
         Protect(luaV_gettable(L, RB(i), RKC(i), ra));
         continue;
       }
-      case OP_SETGLOBAL: {
+      OPCODE_TARGET(SETGLOBAL) {
         TValue g;
         sethvalue(L, &g, cl->env);
         lua_assert(ttisstring(KBx(i)));
         Protect(luaV_settable(L, &g, KBx(i), ra));
         continue;
       }
-      case OP_SETUPVAL: {
+      OPCODE_TARGET(SETUPVAL) {
         UpVal *uv = cl->upvals[GETARG_B(i)];
         setobj(L, uv->v, ra);
         luaC_barrier(L, uv, ra);
         continue;
       }
-      case OP_SETTABLE: {
+      OPCODE_TARGET(SETTABLE) {
         Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
         continue;
       }
-      case OP_NEWTABLE: {
+      OPCODE_TARGET(NEWTABLE) {
         int b = GETARG_B(i);
         int c = GETARG_C(i);
         sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
         Protect(luaC_checkGC(L));
         continue;
       }
-      case OP_SELF: {
+      OPCODE_TARGET(SELF) {
         StkId rb = RB(i);
         setobjs2s(L, ra+1, rb);
         Protect(luaV_gettable(L, rb, RKC(i), ra));
         continue;
       }
-      case OP_ADD: {
+      OPCODE_TARGET(ADD) {
         TValue *rb = RKB(i), *rc= RKC(i);
         arith_op_continue( luai_numadd, try_addint, luai_vectadd );
         Protect(Arith(L, ra, rb, rc, TM_ADD)); \
         continue;
       }
-      case OP_SUB: {
+      OPCODE_TARGET(SUB) {
         TValue *rb = RKB(i), *rc= RKC(i);
         arith_op_continue( luai_numsub, try_subint, luai_vectsub );
         Protect(Arith(L, ra, rb, rc, TM_SUB));
         continue;
       }
-      case OP_MUL: {
+      OPCODE_TARGET(MUL) {
         TValue *rb = RKB(i), *rc= RKC(i);
         arith_op_continue(luai_nummul, try_mulint, luai_vectmul);
         Protect(Arith(L, ra, rb, rc, TM_MUL));
         continue;
       }
-      case OP_DIV: {
+      OPCODE_TARGET(DIV) {
         TValue *rb = RKB(i), *rc= RKC(i);
         arith_op_continue(luai_numdiv, try_divint, luai_vectdiv);
         Protect(Arith(L, ra, rb, rc, TM_DIV));
         continue;
       }
-      case OP_MOD: {
+      OPCODE_TARGET(MOD) {
         TValue *rb = RKB(i), *rc= RKC(i);
         arith_op_continue_scalar(luai_nummod, try_modint);  /* scalars only */
         Protect(Arith(L, ra, rb, rc, TM_MOD));
         continue;
       }
-      case OP_POW: {
+      OPCODE_TARGET(POW) {
         TValue *rb = RKB(i), *rc= RKC(i);
         arith_op_continue(luai_numpow, try_powint, luai_vectpow);
         Protect(Arith(L, ra, rb, rc, TM_POW));
         continue;
       }
-      case OP_UNM: {
+      OPCODE_TARGET(UNM) {
         TValue *rb = RB(i);
         arith_op1_continue(luai_numunm, try_unmint, luai_vectunm);
         Protect(Arith(L, ra, rb, rb, TM_UNM));
         continue;
       }
-      case OP_NOT: {
+      OPCODE_TARGET(NOT) {
         int res = l_isfalse(RB(i));  /* next assignment may change this value */
         setbvalue(ra, res);
         continue;
       }
-      case OP_LEN: {
+      OPCODE_TARGET(LEN) {
         const TValue *rb = RB(i);
         switch (ttype(rb)) {
           case LUA_TTABLE: {
@@ -729,18 +783,18 @@
         }
         continue;
       }
-      case OP_CONCAT: {
+      OPCODE_TARGET(CONCAT) {
         int b = GETARG_B(i);
         int c = GETARG_C(i);
         Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));
         setobjs2s(L, RA(i), base+b);
         continue;
       }
-      case OP_JMP: {
+      OPCODE_TARGET(JMP) {
         dojump(L, pc, GETARG_sBx(i));
         continue;
       }
-      case OP_EQ: {
+      OPCODE_TARGET(EQ) {
         TValue *rb = RKB(i);
         TValue *rc = RKC(i);
         Protect(
@@ -750,7 +804,7 @@
         pc++;
         continue;
       }
-      case OP_LT: {
+      OPCODE_TARGET(LT) {
         Protect(
           if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))
             dojump(L, pc, GETARG_sBx(*pc));
@@ -758,7 +812,7 @@
         pc++;
         continue;
       }
-      case OP_LE: {
+      OPCODE_TARGET(LE) {
         Protect(
           if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))
             dojump(L, pc, GETARG_sBx(*pc));
@@ -766,13 +820,13 @@
         pc++;
         continue;
       }
-      case OP_TEST: {
+      OPCODE_TARGET(TEST) {
         if (l_isfalse(ra) != GETARG_C(i))
           dojump(L, pc, GETARG_sBx(*pc));
         pc++;
         continue;
       }
-      case OP_TESTSET: {
+      OPCODE_TARGET(TESTSET) {
         TValue *rb = RB(i);
         if (l_isfalse(rb) != GETARG_C(i)) {
           setobjs2s(L, ra, rb);
@@ -781,7 +835,7 @@
         pc++;
         continue;
       }
-      case OP_CALL: {
+      OPCODE_TARGET(CALL) {
         int b = GETARG_B(i);
         int nresults = GETARG_C(i) - 1;
         if (b != 0) L->top = ra+b;  /* else previous instruction set top */
@@ -802,7 +856,7 @@
           }
         }
       }
-      case OP_TAILCALL: {
+      OPCODE_TARGET(TAILCALL) {
         int b = GETARG_B(i);
         if (b != 0) L->top = ra+b;  /* else previous instruction set top */
         L->savedpc = pc;
@@ -834,7 +888,7 @@
           }
         }
       }
-      case OP_RETURN: {
+      OPCODE_TARGET(RETURN) {
         int b = GETARG_B(i);
         if (b != 0) L->top = ra+b-1;
         if (L->openupval) luaF_close(L, base);
@@ -849,7 +903,7 @@
           goto reentry;
         }
       }
-      case OP_FORLOOP: {
+      OPCODE_TARGET(FORLOOP) {
         /* If start,step and limit are all integers, we don't need to check
          * against overflow in the looping.
          */
@@ -877,7 +931,7 @@
         }
         continue;
       }
-      case OP_FORPREP: {
+      OPCODE_TARGET(FORPREP) {
         const TValue *init = ra;
         const TValue *plimit = ra+1;
         const TValue *pstep = ra+2;
@@ -900,7 +954,7 @@
         dojump(L, pc, GETARG_sBx(i));
         continue;
       }
-      case OP_TFORLOOP: {
+      OPCODE_TARGET(TFORLOOP) {
         StkId cb = ra + 3;  /* call base */
         setobjs2s(L, cb+2, ra+2);
         setobjs2s(L, cb+1, ra+1);
@@ -916,7 +970,7 @@
         pc++;
         continue;
       }
-      case OP_SETLIST: {
+      OPCODE_TARGET(SETLIST) {
         int n = GETARG_B(i);
         int c = GETARG_C(i);
         int last;
@@ -938,11 +992,11 @@
         }
         continue;
       }
-      case OP_CLOSE: {
+      OPCODE_TARGET(CLOSE) {
         luaF_close(L, ra);
         continue;
       }
-      case OP_CLOSURE: {
+      OPCODE_TARGET(CLOSURE) {
         Proto *p;
         Closure *ncl;
         int nup, j;
@@ -962,7 +1016,7 @@
         Protect(luaC_checkGC(L));
         continue;
       }
-      case OP_VARARG: {
+      OPCODE_TARGET(VARARG) {
         int b = GETARG_B(i) - 1;
         int j;
         CallInfo *ci = L->ci;