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
$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
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;
}
#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
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
/* 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;
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);
}
/* 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);
#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
switch (addr) {
case 0x0092:
/* Special port 92 */
- retval = 0x00;
+ retval = sysctrl->endian << 1;
break;
case 0x0800:
/* Motorola CPU configuration register */
PowerPCCPU *cpu = opaque;
cpu_reset(CPU(cpu));
+
+ /* Reset address */
+ cpu->env.nip = 0xfffffffc;
}
/* PowerPC PREP hardware initialisation */
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);
{
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;
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;
}
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) {
#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
} 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);
}
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) {
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)
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;
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),
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);
}
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);
IPRINTF("imx_timerg_read: Bad offset %x\n",
(int)offset >> 2);
+
return 0;
}
/*
* 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);
}
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);
#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)
* 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;
*/
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,
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);
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);
+ }
+ }
}
}
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:
}
}
-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,
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()
}
};
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;
}
- 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
struct subchannel_id blk_schid;
char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
+uint64_t boot_value;
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);
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;
+ }
}
}
}
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();
_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 */
/*
-Subproject commit 0ad10f26c94a86a0c9c3970e53f9a9f6a744055d
+Subproject commit 8cfdfc43f4c4c8c8dfa4b7cf16f7c19c84eee812
/* 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) */
#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;
#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
#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);
#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,
* 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);
}
}
(*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);
}
}
&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