]> git.proxmox.com Git - mirror_qemu.git/commitdiff
Merge remote-tracking branch 'qemu-kvm/uq/master' into staging
authorAnthony Liguori <aliguori@us.ibm.com>
Mon, 6 May 2013 20:45:08 +0000 (15:45 -0500)
committerAnthony Liguori <aliguori@us.ibm.com>
Mon, 6 May 2013 20:45:08 +0000 (15:45 -0500)
# By Marcelo Tosatti
# Via Gleb Natapov
* qemu-kvm/uq/master:
  kvmvapic: add ioport read accessor

Message-id: cover.1367844188.git.gleb@redhat.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
17 files changed:
configure
hw/net/spapr_llan.c
hw/ppc/e500.c
hw/ppc/prep.c
hw/ppc/spapr_iommu.c
hw/s390x/ipl.c
hw/timer/imx_timer.c
pc-bios/README
pc-bios/s390-ccw.img
pc-bios/s390-ccw/main.c
pc-bios/s390-ccw/start.S
pc-bios/slof.bin
roms/SLOF
target-ppc/cpu.h
target-ppc/mmu_helper.c
target-ppc/translate.c
target-ppc/translate_init.c

index e818e8b357e65ab2b6c6cd7b6cbb08e975c687c4..9439f1c727661df47bcd8a77370ddc85d5178c81 100755 (executable)
--- a/configure
+++ b/configure
@@ -1685,6 +1685,14 @@ if ! has $libtool; then
     libtool=
 fi
 
+# MacOSX ships with a libtool which isn't the GNU one; weed this
+# out by checking whether libtool supports the --version switch
+if test -n "$libtool"; then
+  if ! "$libtool" --version >/dev/null 2>&1; then
+    libtool=
+  fi
+fi
+
 ##########################################
 # Sparse probe
 if test "$sparse" != "no" ; then
@@ -4510,6 +4518,7 @@ for bios_file in \
     $source_path/pc-bios/*.aml \
     $source_path/pc-bios/*.rom \
     $source_path/pc-bios/*.dtb \
+    $source_path/pc-bios/*.img \
     $source_path/pc-bios/openbios-* \
     $source_path/pc-bios/palcode-*
 do
index 3150add3c1cdc5b7881011a7c530e90f3b8ca7fa..03a09f204743b6bf44f1861616a003e1b8ad8464 100644 (file)
@@ -336,6 +336,8 @@ static target_ulong h_register_logical_lan(PowerPCCPU *cpu,
     spapr_vio_dma_set(sdev, VLAN_BD_ADDR(rec_queue), 0, VLAN_BD_LEN(rec_queue));
 
     dev->isopen = 1;
+    qemu_flush_queued_packets(qemu_get_queue(dev->nic));
+
     return H_SUCCESS;
 }
 
index c1bdb6be981734ea5d83967be8c865e3d5281054..c9ae51211e69ea2117ed0daf75efe4acc7af0a75 100644 (file)
@@ -37,6 +37,7 @@
 #include "qemu/host-utils.h"
 #include "hw/pci-host/ppce500.h"
 
+#define EPAPR_MAGIC                (0x45504150)
 #define BINARY_DEVICE_TREE_FILE    "mpc8544ds.dtb"
 #define UIMAGE_LOAD_BASE           0
 #define DTC_LOAD_PAD               0x1800000
@@ -393,11 +394,10 @@ static inline hwaddr booke206_page_size_to_tlb(uint64_t size)
     return 63 - clz64(size >> 10);
 }
 
-static void mmubooke_create_initial_mapping(CPUPPCState *env)
+static int booke206_initial_map_tsize(CPUPPCState *env)
 {
     struct boot_info *bi = env->load_info;
-    ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0);
-    hwaddr size, dt_end;
+    hwaddr dt_end;
     int ps;
 
     /* Our initial TLB entry needs to cover everything from 0 to
@@ -408,6 +408,24 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env)
         /* e500v2 can only do even TLB size bits */
         ps++;
     }
+    return ps;
+}
+
+static uint64_t mmubooke_initial_mapsize(CPUPPCState *env)
+{
+    int tsize;
+
+    tsize = booke206_initial_map_tsize(env);
+    return (1ULL << 10 << tsize);
+}
+
+static void mmubooke_create_initial_mapping(CPUPPCState *env)
+{
+    ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0);
+    hwaddr size;
+    int ps;
+
+    ps = booke206_initial_map_tsize(env);
     size = (ps << MAS1_TSIZE_SHIFT);
     tlb->mas1 = MAS1_VALID | size;
     tlb->mas2 = 0;
@@ -444,6 +462,12 @@ static void ppce500_cpu_reset(void *opaque)
     cs->halted = 0;
     env->gpr[1] = (16<<20) - 8;
     env->gpr[3] = bi->dt_base;
+    env->gpr[4] = 0;
+    env->gpr[5] = 0;
+    env->gpr[6] = EPAPR_MAGIC;
+    env->gpr[7] = mmubooke_initial_mapsize(env);
+    env->gpr[8] = 0;
+    env->gpr[9] = 0;
     env->nip = bi->entry;
     mmubooke_create_initial_mapping(env);
 }
@@ -523,6 +547,7 @@ void ppce500_init(PPCE500Params *params)
 
     /* Fixup Memory size on a alignment boundary */
     ram_size &= ~(RAM_SIZES_ALIGN - 1);
+    params->ram_size = ram_size;
 
     /* Register Memory */
     memory_region_init_ram(ram, "mpc8544ds.ram", ram_size);
index 59c7da3af73e4d9b4964acf869bcbb3098caff2e..be8a50ec4a59d7044df5912fdab1c95d9f467520 100644 (file)
@@ -40,7 +40,9 @@
 #include "hw/isa/pc87312.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/arch_init.h"
+#include "sysemu/qtest.h"
 #include "exec/address-spaces.h"
+#include "elf.h"
 
 //#define HARD_DEBUG_PPC_IO
 //#define DEBUG_PPC_IO
@@ -267,7 +269,7 @@ static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
     switch (addr) {
     case 0x0092:
         /* Special port 92 */
-        retval = 0x00;
+        retval = sysctrl->endian << 1;
         break;
     case 0x0800:
         /* Motorola CPU configuration register */
@@ -427,6 +429,9 @@ static void ppc_prep_reset(void *opaque)
     PowerPCCPU *cpu = opaque;
 
     cpu_reset(CPU(cpu));
+
+    /* Reset address */
+    cpu->env.nip = 0xfffffffc;
 }
 
 /* PowerPC PREP hardware initialisation */
@@ -502,18 +507,29 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
         bios_name = BIOS_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
     if (filename) {
-        bios_size = get_image_size(filename);
+        bios_size = load_elf(filename, NULL, NULL, NULL,
+                             NULL, NULL, 1, ELF_MACHINE, 0);
+        if (bios_size < 0) {
+            bios_size = get_image_size(filename);
+            if (bios_size > 0 && bios_size <= BIOS_SIZE) {
+                hwaddr bios_addr;
+                bios_size = (bios_size + 0xfff) & ~0xfff;
+                bios_addr = (uint32_t)(-bios_size);
+                bios_size = load_image_targphys(filename, bios_addr, bios_size);
+            }
+            if (bios_size > BIOS_SIZE) {
+                fprintf(stderr, "qemu: PReP bios '%s' is too large (0x%x)\n",
+                        bios_name, bios_size);
+                exit(1);
+            }
+        }
     } else {
         bios_size = -1;
     }
-    if (bios_size > 0 && bios_size <= BIOS_SIZE) {
-        hwaddr bios_addr;
-        bios_size = (bios_size + 0xfff) & ~0xfff;
-        bios_addr = (uint32_t)(-bios_size);
-        bios_size = load_image_targphys(filename, bios_addr, bios_size);
-    }
-    if (bios_size < 0 || bios_size > BIOS_SIZE) {
-        hw_error("qemu: could not load PPC PREP bios '%s'\n", bios_name);
+    if (bios_size < 0 && !qtest_enabled()) {
+        fprintf(stderr, "qemu: could not load PPC PReP bios '%s'\n",
+                bios_name);
+        exit(1);
     }
     if (filename) {
         g_free(filename);
index d2782cfb39ac5f91806bb4131a4ab78b7adf1afa..e1fe94115f80bfa10c425f06dfc75f3fbde760b0 100644 (file)
@@ -55,6 +55,12 @@ static sPAPRTCETable *spapr_tce_find_by_liobn(uint32_t liobn)
 {
     sPAPRTCETable *tcet;
 
+    if (liobn & 0xFFFFFFFF00000000ULL) {
+        hcall_dprintf("Request for out-of-bounds LIOBN 0x" TARGET_FMT_lx "\n",
+                      liobn);
+        return NULL;
+    }
+
     QLIST_FOREACH(tcet, &spapr_tce_tables, list) {
         if (tcet->liobn == liobn) {
             return tcet;
@@ -199,7 +205,7 @@ static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
     sPAPRTCE *tcep;
 
     if (ioba >= tcet->window_size) {
-        hcall_dprintf("spapr_vio_put_tce on out-of-boards IOBA 0x"
+        hcall_dprintf("spapr_vio_put_tce on out-of-bounds IOBA 0x"
                       TARGET_FMT_lx "\n", ioba);
         return H_PARAMETER;
     }
@@ -218,12 +224,6 @@ static target_ulong h_put_tce(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     target_ulong tce = args[2];
     sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
 
-    if (liobn & 0xFFFFFFFF00000000ULL) {
-        hcall_dprintf("spapr_vio_put_tce on out-of-boundsw LIOBN "
-                      TARGET_FMT_lx "\n", liobn);
-        return H_PARAMETER;
-    }
-
     ioba &= ~(SPAPR_TCE_PAGE_SIZE - 1);
 
     if (tcet) {
index ace5ff50d1784992d1f5e8a9f8101bcc0b8b427a..0aeb003c9d559587f7a959340f9d8756d5bb7d3b 100644 (file)
@@ -16,6 +16,8 @@
 #include "elf.h"
 #include "hw/loader.h"
 #include "hw/sysbus.h"
+#include "hw/s390x/virtio-ccw.h"
+#include "hw/s390x/css.h"
 
 #define KERN_IMAGE_START                0x010000UL
 #define KERN_PARM_AREA                  0x010480UL
@@ -57,16 +59,6 @@ typedef struct S390IPLState {
 } S390IPLState;
 
 
-static void s390_ipl_cpu(uint64_t pswaddr)
-{
-    S390CPU *cpu = S390_CPU(qemu_get_cpu(0));
-    CPUS390XState *env = &cpu->env;
-
-    env->psw.addr = pswaddr;
-    env->psw.mask = IPL_PSW_MASK;
-    s390_add_running_cpu(cpu);
-}
-
 static int s390_ipl_init(SysBusDevice *dev)
 {
     S390IPLState *ipl = S390_IPL(dev);
@@ -82,6 +74,10 @@ static int s390_ipl_init(SysBusDevice *dev)
         }
 
         bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (bios_filename == NULL) {
+            hw_error("could not find stage1 bootloader\n");
+        }
+
         bios_size = load_elf(bios_filename, NULL, NULL, &ipl->start_addr, NULL,
                              NULL, 1, ELF_MACHINE, 0);
         if (bios_size == -1UL) {
@@ -151,8 +147,28 @@ static Property s390_ipl_properties[] = {
 static void s390_ipl_reset(DeviceState *dev)
 {
     S390IPLState *ipl = S390_IPL(dev);
+    S390CPU *cpu = S390_CPU(qemu_get_cpu(0));
+    CPUS390XState *env = &cpu->env;
 
-    s390_ipl_cpu(ipl->start_addr);
+    env->psw.addr = ipl->start_addr;
+    env->psw.mask = IPL_PSW_MASK;
+
+    if (!ipl->kernel) {
+        /* booting firmware, tell what device to boot from */
+        DeviceState *dev_st = get_boot_device(0);
+        VirtioCcwDevice *ccw_dev = (VirtioCcwDevice *) object_dynamic_cast(
+                OBJECT(&(dev_st->parent_obj)), "virtio-blk-ccw");
+
+        if (ccw_dev) {
+            env->regs[7] = ccw_dev->sch->cssid << 24 |
+                           ccw_dev->sch->ssid << 16 |
+                           ccw_dev->sch->devno;
+        } else {
+            env->regs[7] = -1;
+        }
+    }
+
+    s390_add_running_cpu(cpu);
 }
 
 static void s390_ipl_class_init(ObjectClass *klass, void *data)
index 03197e3f5471ab5f613e41307e9b92b6bd2f887f..7693bb7364cddbc2baaaca854c3e141e971470a7 100644 (file)
@@ -95,6 +95,10 @@ typedef struct {
     uint32_t sr;
     uint32_t ir;
     uint32_t ocr1;
+    uint32_t ocr2;
+    uint32_t ocr3;
+    uint32_t icr1;
+    uint32_t icr2;
     uint32_t cnt;
 
     uint32_t waiting_rov;
@@ -103,15 +107,19 @@ typedef struct {
 
 static const VMStateDescription vmstate_imx_timerg = {
     .name = "imx-timerg",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
+    .version_id = 2,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 2,
     .fields      = (VMStateField[]) {
         VMSTATE_UINT32(cr, IMXTimerGState),
         VMSTATE_UINT32(pr, IMXTimerGState),
         VMSTATE_UINT32(sr, IMXTimerGState),
         VMSTATE_UINT32(ir, IMXTimerGState),
         VMSTATE_UINT32(ocr1, IMXTimerGState),
+        VMSTATE_UINT32(ocr2, IMXTimerGState),
+        VMSTATE_UINT32(ocr3, IMXTimerGState),
+        VMSTATE_UINT32(icr1, IMXTimerGState),
+        VMSTATE_UINT32(icr2, IMXTimerGState),
         VMSTATE_UINT32(cnt, IMXTimerGState),
         VMSTATE_UINT32(waiting_rov, IMXTimerGState),
         VMSTATE_PTIMER(timer, IMXTimerGState),
@@ -156,7 +164,6 @@ static void imx_timerg_update(IMXTimerGState *s)
             s->ir & GPT_SR_ROV ? "ROV" : "",
             s->cr & GPT_CR_EN ? "CR_EN" : "Not Enabled");
 
-
     qemu_set_irq(s->irq, (s->cr & GPT_CR_EN) && flags);
 }
 
@@ -221,6 +228,21 @@ static uint64_t imx_timerg_read(void *opaque, hwaddr offset,
         DPRINTF(" ocr1 = %x\n", s->ocr1);
         return s->ocr1;
 
+    case 5: /* Output Compare Register 2 */
+        DPRINTF(" ocr2 = %x\n", s->ocr2);
+        return s->ocr2;
+
+    case 6: /* Output Compare Register 3 */
+        DPRINTF(" ocr3 = %x\n", s->ocr3);
+        return s->ocr3;
+
+    case 7: /* input Capture Register 1 */
+        DPRINTF(" icr1 = %x\n", s->icr1);
+        return s->icr1;
+
+    case 8: /* input Capture Register 2 */
+        DPRINTF(" icr2 = %x\n", s->icr2);
+        return s->icr2;
 
     case 9: /* cnt */
         imx_timerg_update_counts(s);
@@ -230,6 +252,7 @@ static uint64_t imx_timerg_read(void *opaque, hwaddr offset,
 
     IPRINTF("imx_timerg_read: Bad offset %x\n",
             (int)offset >> 2);
+
     return 0;
 }
 
@@ -240,14 +263,20 @@ static void imx_timerg_reset(DeviceState *dev)
     /*
      * Soft reset doesn't touch some bits; hard reset clears them
      */
-    s->cr &= ~(GPT_CR_EN|GPT_CR_DOZEN|GPT_CR_WAITEN|GPT_CR_DBGEN);
+    s->cr &= ~(GPT_CR_EN|GPT_CR_ENMOD|GPT_CR_STOPEN|GPT_CR_DOZEN|
+               GPT_CR_WAITEN|GPT_CR_DBGEN);
     s->sr = 0;
     s->pr = 0;
     s->ir = 0;
     s->cnt = 0;
     s->ocr1 = TIMER_MAX;
+    s->ocr2 = TIMER_MAX;
+    s->ocr3 = TIMER_MAX;
+    s->icr1 = 0;
+    s->icr2 = 0;
     ptimer_stop(s->timer);
     ptimer_set_limit(s->timer, TIMER_MAX, 1);
+    ptimer_set_count(s->timer, TIMER_MAX);
     imx_timerg_set_freq(s);
 }
 
@@ -323,6 +352,8 @@ static void imx_timerg_write(void *opaque, hwaddr offset,
         s->ocr1 = value;
         return;
 
+    case 5: /* OCR2 -- output compare register */
+    case 6: /* OCR3 -- output compare register */
     default:
         IPRINTF("imx_timerg_write: Bad offset %x\n",
                 (int)offset >> 2);
@@ -411,7 +442,7 @@ static int imx_timerg_init(SysBusDevice *dev)
 #define CR_SWR      (1 << 16)
 #define CR_IOVW     (1 << 17)
 #define CR_DBGEN    (1 << 18)
-#define CR_EPIT     (1 << 19)
+#define CR_WAITEN   (1 << 19)
 #define CR_DOZEN    (1 << 20)
 #define CR_STOPEN   (1 << 21)
 #define CR_CLKSRC_SHIFT (24)
@@ -423,24 +454,26 @@ static int imx_timerg_init(SysBusDevice *dev)
  * These are typical.
  */
 static const IMXClk imx_timerp_clocks[] =  {
-    0,        /* disabled */
-    IPG, /* ipg_clk, ~532MHz */
-    IPG, /* ipg_clk_highfreq */
-    CLK_32k,    /* ipg_clk_32k -- ~32kHz */
+    0,        /* 00 disabled */
+    IPG,      /* 01 ipg_clk, ~532MHz */
+    IPG,      /* 10 ipg_clk_highfreq */
+    CLK_32k,  /* 11 ipg_clk_32k -- ~32kHz */
 };
 
 typedef struct {
     SysBusDevice busdev;
-    ptimer_state *timer;
+    ptimer_state *timer_reload;
+    ptimer_state *timer_cmp;
     MemoryRegion iomem;
     DeviceState *ccm;
 
     uint32_t cr;
+    uint32_t sr;
     uint32_t lr;
     uint32_t cmp;
+    uint32_t cnt;
 
     uint32_t freq;
-    int int_level;
     qemu_irq irq;
 } IMXTimerPState;
 
@@ -449,23 +482,63 @@ typedef struct {
  */
 static void imx_timerp_update(IMXTimerPState *s)
 {
-    if (s->int_level && (s->cr & CR_OCIEN)) {
+    if (s->sr && (s->cr & CR_OCIEN)) {
         qemu_irq_raise(s->irq);
     } else {
         qemu_irq_lower(s->irq);
     }
 }
 
+static void set_timerp_freq(IMXTimerPState *s)
+{
+    int clksrc;
+    unsigned prescaler;
+    uint32_t freq;
+
+    clksrc = (s->cr & CR_CLKSRC_MASK) >> CR_CLKSRC_SHIFT;
+    prescaler = 1 + ((s->cr >> CR_PRESCALE_SHIFT) & CR_PRESCALE_MASK);
+    freq = imx_clock_frequency(s->ccm, imx_timerp_clocks[clksrc]) / prescaler;
+
+    s->freq = freq;
+    DPRINTF("Setting ptimer frequency to %u\n", freq);
+
+    if (freq) {
+        ptimer_set_freq(s->timer_reload, freq);
+        ptimer_set_freq(s->timer_cmp, freq);
+    }
+}
+
 static void imx_timerp_reset(DeviceState *dev)
 {
     IMXTimerPState *s = container_of(dev, IMXTimerPState, busdev.qdev);
 
-    s->cr = 0;
+    /*
+     * Soft reset doesn't touch some bits; hard reset clears them
+     */
+    s->cr &= ~(CR_EN|CR_ENMOD|CR_STOPEN|CR_DOZEN|CR_WAITEN|CR_DBGEN);
+    s->sr = 0;
     s->lr = TIMER_MAX;
-    s->int_level = 0;
     s->cmp = 0;
-    ptimer_stop(s->timer);
-    ptimer_set_count(s->timer, TIMER_MAX);
+    s->cnt = 0;
+    /* stop both timers */
+    ptimer_stop(s->timer_cmp);
+    ptimer_stop(s->timer_reload);
+    /* compute new frequency */
+    set_timerp_freq(s);
+    /* init both timers to TIMER_MAX */
+    ptimer_set_limit(s->timer_cmp, TIMER_MAX, 1);
+    ptimer_set_limit(s->timer_reload, TIMER_MAX, 1);
+    if (s->freq && (s->cr & CR_EN)) {
+        /* if the timer is still enabled, restart it */
+        ptimer_run(s->timer_reload, 1);
+    }
+}
+
+static uint32_t imx_timerp_update_counts(IMXTimerPState *s)
+{
+     s->cnt = ptimer_get_count(s->timer_reload);
+
+     return s->cnt;
 }
 
 static uint64_t imx_timerp_read(void *opaque, hwaddr offset,
@@ -480,8 +553,8 @@ static uint64_t imx_timerp_read(void *opaque, hwaddr offset,
         return s->cr;
 
     case 1: /* Status Register */
-        DPRINTF("int_level %x\n", s->int_level);
-        return s->int_level;
+        DPRINTF("sr %x\n", s->sr);
+        return s->sr;
 
     case 2: /* LR - ticks*/
         DPRINTF("lr %x\n", s->lr);
@@ -492,28 +565,29 @@ static uint64_t imx_timerp_read(void *opaque, hwaddr offset,
         return s->cmp;
 
     case 4: /* CNT */
-        return ptimer_get_count(s->timer);
+        imx_timerp_update_counts(s);
+        DPRINTF(" cnt = %x\n", s->cnt);
+        return s->cnt;
     }
+
     IPRINTF("imx_timerp_read: Bad offset %x\n",
             (int)offset >> 2);
     return 0;
 }
 
-static void set_timerp_freq(IMXTimerPState *s)
+static void imx_reload_compare_timer(IMXTimerPState *s)
 {
-    int clksrc;
-    unsigned prescaler;
-    uint32_t freq;
-
-    clksrc = (s->cr & CR_CLKSRC_MASK) >> CR_CLKSRC_SHIFT;
-    prescaler = 1 + ((s->cr >> CR_PRESCALE_SHIFT) & CR_PRESCALE_MASK);
-    freq = imx_clock_frequency(s->ccm, imx_timerp_clocks[clksrc]) / prescaler;
-
-    s->freq = freq;
-    DPRINTF("Setting ptimer frequency to %u\n", freq);
-
-    if (freq) {
-        ptimer_set_freq(s->timer, freq);
+    if ((s->cr & CR_OCIEN) && s->cmp) {
+        /* if the compare feature is on */
+        uint32_t tmp = imx_timerp_update_counts(s);
+        if (tmp > s->cmp) {
+            /* reinit the cmp timer if required */
+            ptimer_set_count(s->timer_cmp, tmp - s->cmp);
+            if ((s->cr & CR_EN)) {
+                /* Restart the cmp timer if required */
+                ptimer_run(s->timer_cmp, 0);
+            }
+        }
     }
 }
 
@@ -526,40 +600,62 @@ static void imx_timerp_write(void *opaque, hwaddr offset,
 
     switch (offset >> 2) {
     case 0: /* CR */
-        if (value & CR_SWR) {
+        s->cr = value & 0x03ffffff;
+        if (s->cr & CR_SWR) {
+            /* handle the reset */
             imx_timerp_reset(&s->busdev.qdev);
-            value &= ~CR_SWR;
+        } else {
+            set_timerp_freq(s);
         }
-        s->cr = value & 0x03ffffff;
-        set_timerp_freq(s);
 
         if (s->freq && (s->cr & CR_EN)) {
-            if (!(s->cr & CR_ENMOD)) {
-                ptimer_set_count(s->timer, s->lr);
+            if (s->cr & CR_ENMOD) {
+                if (s->cr & CR_RLD) {
+                    ptimer_set_limit(s->timer_reload, s->lr, 1);
+                } else {
+                    ptimer_set_limit(s->timer_reload, TIMER_MAX, 1);
+                }
             }
-            ptimer_run(s->timer, 0);
+
+            imx_reload_compare_timer(s);
+
+            ptimer_run(s->timer_reload, 1);
         } else {
-            ptimer_stop(s->timer);
+            /* stop both timers */
+            ptimer_stop(s->timer_reload);
+            ptimer_stop(s->timer_cmp);
         }
         break;
 
     case 1: /* SR - ACK*/
-        s->int_level = 0;
-        imx_timerp_update(s);
+        /* writing 1 to OCIF clear the OCIF bit */
+        if (value & 0x01) {
+            s->sr = 0;
+            imx_timerp_update(s);
+        }
         break;
 
     case 2: /* LR - set ticks */
         s->lr = value;
-        ptimer_set_limit(s->timer, value, !!(s->cr & CR_IOVW));
+
+        if (s->cr & CR_RLD) {
+            /* Also set the limit if the LRD bit is set */
+            /* If IOVW bit is set then set the timer value */
+            ptimer_set_limit(s->timer_reload, s->lr, s->cr & CR_IOVW);
+        } else if (s->cr & CR_IOVW) {
+            /* If IOVW bit is set then set the timer value */
+            ptimer_set_count(s->timer_reload, s->lr);
+        }
+
+        imx_reload_compare_timer(s);
+
         break;
 
     case 3: /* CMP */
         s->cmp = value;
-        if (value) {
-            IPRINTF(
-                "Values for EPIT comparison other than zero not supported\n"
-            );
-        }
+
+        imx_reload_compare_timer(s);
+
         break;
 
     default:
@@ -568,16 +664,50 @@ static void imx_timerp_write(void *opaque, hwaddr offset,
     }
 }
 
-static void imx_timerp_tick(void *opaque)
+static void imx_timerp_reload(void *opaque)
 {
     IMXTimerPState *s = (IMXTimerPState *)opaque;
 
-   DPRINTF("imxp tick\n");
-    if (!(s->cr & CR_RLD)) {
-        ptimer_set_count(s->timer, TIMER_MAX);
+    DPRINTF("imxp reload\n");
+
+    if (!(s->cr & CR_EN)) {
+        return;
+    }
+
+    if (s->cr & CR_RLD) {
+        ptimer_set_limit(s->timer_reload, s->lr, 1);
+    } else {
+        ptimer_set_limit(s->timer_reload, TIMER_MAX, 1);
+    }
+
+    if (s->cr & CR_OCIEN) {
+        /* if compare register is 0 then we handle the interrupt here */
+        if (s->cmp == 0) {
+            s->sr = 1;
+            imx_timerp_update(s);
+        } else if (s->cmp <= s->lr) {
+            /* We should launch the compare register */
+            ptimer_set_count(s->timer_cmp, s->lr - s->cmp);
+            ptimer_run(s->timer_cmp, 0);
+        } else {
+            IPRINTF("imxp reload: s->lr < s->cmp\n");
+        }
+    }
+}
+
+static void imx_timerp_cmp(void *opaque)
+{
+    IMXTimerPState *s = (IMXTimerPState *)opaque;
+
+    DPRINTF("imxp compare\n");
+
+    ptimer_stop(s->timer_cmp);
+
+    /* compare register is not 0 */
+    if (s->cmp) {
+        s->sr = 1;
+        imx_timerp_update(s);
     }
-    s->int_level = 1;
-    imx_timerp_update(s);
 }
 
 void imx_timerp_create(const hwaddr addr,
@@ -600,16 +730,18 @@ static const MemoryRegionOps imx_timerp_ops = {
 
 static const VMStateDescription vmstate_imx_timerp = {
     .name = "imx-timerp",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
+    .version_id = 2,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 2,
     .fields      = (VMStateField[]) {
         VMSTATE_UINT32(cr, IMXTimerPState),
+        VMSTATE_UINT32(sr, IMXTimerPState),
         VMSTATE_UINT32(lr, IMXTimerPState),
         VMSTATE_UINT32(cmp, IMXTimerPState),
+        VMSTATE_UINT32(cnt, IMXTimerPState),
         VMSTATE_UINT32(freq, IMXTimerPState),
-        VMSTATE_INT32(int_level, IMXTimerPState),
-        VMSTATE_PTIMER(timer, IMXTimerPState),
+        VMSTATE_PTIMER(timer_reload, IMXTimerPState),
+        VMSTATE_PTIMER(timer_cmp, IMXTimerPState),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -620,15 +752,17 @@ static int imx_timerp_init(SysBusDevice *dev)
     QEMUBH *bh;
 
     DPRINTF("imx_timerp_init\n");
-
     sysbus_init_irq(dev, &s->irq);
     memory_region_init_io(&s->iomem, &imx_timerp_ops,
                           s, "imxp-timer",
                           0x00001000);
     sysbus_init_mmio(dev, &s->iomem);
 
-    bh = qemu_bh_new(imx_timerp_tick, s);
-    s->timer = ptimer_init(bh);
+    bh = qemu_bh_new(imx_timerp_reload, s);
+    s->timer_reload = ptimer_init(bh);
+
+    bh = qemu_bh_new(imx_timerp_cmp, s);
+    s->timer_cmp = ptimer_init(bh);
 
     return 0;
 }
index 7b4dfed6cf0c4c361d18544bfb6137575e410fed..030d92a049b9cc9af00e3a28712f76a635f98237 100644 (file)
@@ -16,8 +16,8 @@
 
 - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
   implementation for certain IBM POWER hardware.  The sources are at
-  https://github.com/dgibson/SLOF, and the image currently in qemu is
-  built from git tag qemu-slof-20121018.
+  https://github.com/aik/SLOF, and the image currently in qemu is
+  built from git tag qemu-slof-20130430.
 
 - sgabios (the Serial Graphics Adapter option ROM) provides a means for
   legacy x86 software to communicate with an attached serial console as
index 149cf70140e9e690960b49337b4e5f419c452a86..1b2a11e728d1e17d386d64a9f13a90b4635dc2ba 100644 (file)
Binary files a/pc-bios/s390-ccw.img and b/pc-bios/s390-ccw.img differ
index fd40fa582a4a39792bd92a612eb8be6963461346..1665c572259cb0c2b0e62a5dfab4281a79e6138f 100644 (file)
@@ -12,6 +12,7 @@
 
 struct subchannel_id blk_schid;
 char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
+uint64_t boot_value;
 
 void virtio_panic(const char *string)
 {
@@ -20,15 +21,22 @@ void virtio_panic(const char *string)
     while (1) { }
 }
 
-static void virtio_setup(void)
+static void virtio_setup(uint64_t dev_info)
 {
     struct schib schib;
     int i;
     int r;
     bool found = false;
-
+    bool check_devno = false;
+    uint16_t dev_no = -1;
     blk_schid.one = 1;
 
+    if (dev_info != -1) {
+        check_devno = true;
+        dev_no = dev_info & 0xffff;
+        debug_print_int("device no. ", dev_no);
+    }
+
     for (i = 0; i < 0x10000; i++) {
         blk_schid.sch_no = i;
         r = stsch_err(blk_schid, &schib);
@@ -36,9 +44,11 @@ static void virtio_setup(void)
             break;
         }
         if (schib.pmcw.dnv) {
-            if (virtio_is_blk(blk_schid)) {
-                found = true;
-                break;
+            if (!check_devno || (schib.pmcw.dev == dev_no)) {
+                if (virtio_is_blk(blk_schid)) {
+                    found = true;
+                    break;
+                }
             }
         }
     }
@@ -53,7 +63,9 @@ static void virtio_setup(void)
 int main(void)
 {
     sclp_setup();
-    virtio_setup();
+    debug_print_int("boot reg[7] ", boot_value);
+    virtio_setup(boot_value);
+
     if (zipl_load() < 0)
         sclp_print("Failed to load OS from hard disk\n");
     disabled_wait();
index 09deee7fc052c0f87d82d48eef8cc48e5236c980..5d5df0d616efd1a6028acbeccbcd7666a5611e7f 100644 (file)
@@ -14,6 +14,8 @@
 _start:
 
 larl   %r15, stack + 0x8000    /* Set up stack */
+larl    %r6, boot_value
+stg     %r7, 0(%r6)     /* save the boot_value before any function calls */
 j      main                    /* And call C */
 
 /*
index 3410f4fff40ff4a93d8963bf63fd6c1439f8b19c..092e58a46e1d511410793f94a0ca415657dc72b7 100644 (file)
Binary files a/pc-bios/slof.bin and b/pc-bios/slof.bin differ
index 0ad10f26c94a86a0c9c3970e53f9a9f6a744055d..8cfdfc43f4c4c8c8dfa4b7cf16f7c19c84eee812 160000 (submodule)
--- a/roms/SLOF
+++ b/roms/SLOF
@@ -1 +1 @@
-Subproject commit 0ad10f26c94a86a0c9c3970e53f9a9f6a744055d
+Subproject commit 8cfdfc43f4c4c8c8dfa4b7cf16f7c19c84eee812
index 7cacb56bc5e83bb3bdddb08a225dbd5130adf89e..aa1d013c316031aa832b260d7783506b335940ca 100644 (file)
@@ -119,6 +119,9 @@ enum powerpc_mmu_t {
     /* Architecture 2.06 variant                               */
     POWERPC_MMU_2_06       = POWERPC_MMU_64 | POWERPC_MMU_1TSEG
                              | POWERPC_MMU_AMR | 0x00000003,
+    /* Architecture 2.06 "degraded" (no 1T segments)           */
+    POWERPC_MMU_2_06a      = POWERPC_MMU_64 | 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) */
index acf01331f16875676c6d352c8a0f265d56d9a321..68d5415e54d0a664af314b52271646dc4de71e17 100644 (file)
@@ -1188,6 +1188,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env)
 #if defined(TARGET_PPC64)
     case POWERPC_MMU_64B:
     case POWERPC_MMU_2_06:
+    case POWERPC_MMU_2_06a:
     case POWERPC_MMU_2_06d:
         dump_slb(f, cpu_fprintf, env);
         break;
@@ -1324,6 +1325,7 @@ hwaddr cpu_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
 #if defined(TARGET_PPC64)
     case POWERPC_MMU_64B:
     case POWERPC_MMU_2_06:
+    case POWERPC_MMU_2_06a:
     case POWERPC_MMU_2_06d:
         return ppc_hash64_get_phys_page_debug(env, addr);
 #endif
@@ -1815,6 +1817,7 @@ void ppc_tlb_invalidate_all(CPUPPCState *env)
 #if defined(TARGET_PPC64)
     case POWERPC_MMU_64B:
     case POWERPC_MMU_2_06:
+    case POWERPC_MMU_2_06a:
     case POWERPC_MMU_2_06d:
 #endif /* defined(TARGET_PPC64) */
         tlb_flush(env, 1);
@@ -1884,6 +1887,7 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
 #if defined(TARGET_PPC64)
     case POWERPC_MMU_64B:
     case POWERPC_MMU_2_06:
+    case POWERPC_MMU_2_06a:
     case POWERPC_MMU_2_06d:
         /* tlbie invalidate TLBs for all segments */
         /* XXX: given the fact that there are too many segments to invalidate,
index 1a84653983b5a9b305f900df10a01fa8598c0084..0886f4d699554f260ec734b809a7e17b4abbd2e1 100644 (file)
@@ -4005,19 +4005,19 @@ static inline void gen_op_mfspr(DisasContext *ctx)
              * allowing userland application to read the PVR
              */
             if (sprn != SPR_PVR) {
-                qemu_log("Trying to read privileged spr %d %03x at "
-                         TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
-                printf("Trying to read privileged spr %d %03x at "
-                       TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
+                qemu_log("Trying to read privileged spr %d (0x%03x) at "
+                         TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
+                printf("Trying to read privileged spr %d (0x%03x) at "
+                       TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
             }
             gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
         }
     } else {
         /* Not defined */
-        qemu_log("Trying to read invalid spr %d %03x at "
-                    TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
-        printf("Trying to read invalid spr %d %03x at " TARGET_FMT_lx "\n",
-               sprn, sprn, ctx->nip);
+        qemu_log("Trying to read invalid spr %d (0x%03x) at "
+                 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
+        printf("Trying to read invalid spr %d (0x%03x) at "
+               TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
         gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
     }
 }
@@ -4150,18 +4150,18 @@ static void gen_mtspr(DisasContext *ctx)
             (*write_cb)(ctx, sprn, rS(ctx->opcode));
         } else {
             /* Privilege exception */
-            qemu_log("Trying to write privileged spr %d %03x at "
-                     TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
-            printf("Trying to write privileged spr %d %03x at " TARGET_FMT_lx
-                   "\n", sprn, sprn, ctx->nip);
+            qemu_log("Trying to write privileged spr %d (0x%03x) at "
+                     TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
+            printf("Trying to write privileged spr %d (0x%03x) at "
+                   TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
             gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
         }
     } else {
         /* Not defined */
-        qemu_log("Trying to write invalid spr %d %03x at "
-                 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
-        printf("Trying to write invalid spr %d %03x at " TARGET_FMT_lx "\n",
-               sprn, sprn, ctx->nip);
+        qemu_log("Trying to write invalid spr %d (0x%03x) at "
+                 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
+        printf("Trying to write invalid spr %d (0x%03x) at "
+               TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
         gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
     }
 }
index 6feb62abcd88e3c6c0be056d45c17c6f93685a53..021a31e2098ebb16bda432988f5950b5fa2f92c9 100644 (file)
@@ -7010,6 +7010,10 @@ static void init_proc_POWER7 (CPUPPCState *env)
                  &spr_read_generic, &spr_write_generic,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
+    spr_register(env, SPR_PPR, "PPR",
+                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
 #if !defined(CONFIG_USER_ONLY)
     env->slb_nr = 32;
 #endif