ppc patch queue for 2016-05-27 (first pull for qemu-2.7)

I'm back from holidays now, and have re-collated the ppc patch queue.
 This is a first pull request against the qemu-2.7 branch, mostly
 consisting of patches which were posted before the 2.6 freeze, but
 weren't suitable for late inclusion in the 2.6 branch.
 
  * Assorted bugfixes and cleanups
  * Some preliminary patches towards dynamic DMA windows and CPU hotplug
  * Significant performance impovement for the spapr-llan device
  * Added myself to MAINTAINERS for ppc (overdue)
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJXR7kvAAoJEGw4ysog2bOSjogQAI93sJ2zAEJ3kPm8dRUfiBvu
 UWQPMgkuuX96Ujby1sWcTPAAJNJCmgdbqtzL4jCJpANMIirpFzHoissScFsjS1Vs
 /q6VZO7D3XMdXsBstWt1Sz5e3tl2LQJW2AZEtf4f4/of5TwHNMVPS70HEL7nSuVH
 nn5tI/KDTiuY1bEh8x1Kiu444eM3LWHddvQPuaptR6SeT5VYVJejuPb87C4kIHme
 TZXtxn7bCgDg/bwsHmq5QndjMp4VxDQ7ZxHkjtdN6kA0oT9GH/dK4f+ngmMBqHzQ
 dBjgTX7CGzFn/0V14O0akddaQUITsUQqneJx57GAp0uXO/erY01IibH+BFp62Frx
 83GeHuzZQ0/NdytGTiRnL8W6gQgNyHE9NaTeZHgKuxPkPUHjjNtUthB7U7/mDJPP
 hq/G+xdNdN2BW9U/P3XG9WqmpRfr+wnYdKNvx6zNS9PTXbW8DlL5LAcUslGKMXhD
 dexsDvS3I2lhP7CzpVegFLq1EYuBAP35+4KVu/RAXTBdJg4yjIdhQ6sgoCCgU3fH
 Dd4eNNK3Px25+uIXoLCJ1Ag9rKsmI8wOn4fXuZmKu7lNhw1lgebGgE3yM4T5CEuD
 lpUp4aKqYOpZVsdMuRNdk77wlmIoCiVvtJ0Oj/FrjAtJRxarc5GODZj0m+E8ZJEA
 2oJzmW9NzA+zRWeH/0NM
 =g96T
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.7-20160527' into staging

ppc patch queue for 2016-05-27 (first pull for qemu-2.7)

I'm back from holidays now, and have re-collated the ppc patch queue.
This is a first pull request against the qemu-2.7 branch, mostly
consisting of patches which were posted before the 2.6 freeze, but
weren't suitable for late inclusion in the 2.6 branch.

 * Assorted bugfixes and cleanups
 * Some preliminary patches towards dynamic DMA windows and CPU hotplug
 * Significant performance impovement for the spapr-llan device
 * Added myself to MAINTAINERS for ppc (overdue)

# gpg: Signature made Fri 27 May 2016 04:04:15 BST using RSA key ID 20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg:                 aka "David Gibson (Red Hat) <dgibson@redhat.com>"
# gpg:                 aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E  87DC 6C38 CACA 20D9 B392

* remotes/dgibson/tags/ppc-for-2.7-20160527:
  MAINTAINERS: Add David Gibson as ppc maintainer
  spapr_iommu: Move table allocation to helpers
  spapr_iommu: Finish renaming vfio_accel to need_vfio
  spapr_pci: Use correct DMA LIOBN when composing the device tree
  spapr: ensure device trees are always associated with DRC
  PPC/KVM: early validation of vcpu id
  Added negative check for get_image_size()
  hw/net/spapr_llan: Provide counter with dropped rx frames to the guest
  hw/net/spapr_llan: Delay flushing of the RX queue while adding new RX buffers
  target-ppc: Cleanups to rldinm, rldnm, rldimi
  target-ppc: Use 32-bit rotate instead of deposit + 64-bit rotate
  target-ppc: Use movcond in isel
  target-ppc: Correct KVM synchronization for ppc_hash64_set_external_hpt()

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2016-05-27 10:11:11 +01:00
commit 34c99d7b93
12 changed files with 242 additions and 208 deletions

View File

@ -165,6 +165,7 @@ F: hw/openrisc/
F: tests/tcg/openrisc/
PowerPC
M: David Gibson <david@gibson.dropbear.id.au>
M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org
S: Maintained

View File

@ -110,6 +110,7 @@ typedef struct VIOsPAPRVLANDevice {
hwaddr buf_list;
uint32_t add_buf_ptr, use_buf_ptr, rx_bufs;
hwaddr rxq_ptr;
QEMUTimer *rxp_timer;
uint32_t compat_flags; /* Compatability flags for migration */
RxBufPool *rx_pool[RX_MAX_POOLS]; /* Receive buffer descriptor pools */
} VIOsPAPRVLANDevice;
@ -121,6 +122,21 @@ static int spapr_vlan_can_receive(NetClientState *nc)
return (dev->isopen && dev->rx_bufs > 0);
}
/**
* The last 8 bytes of the receive buffer list page (that has been
* supplied by the guest with the H_REGISTER_LOGICAL_LAN call) contain
* a counter for frames that have been dropped because there was no
* suitable receive buffer available. This function is used to increase
* this counter by one.
*/
static void spapr_vlan_record_dropped_rx_frame(VIOsPAPRVLANDevice *dev)
{
uint64_t cnt;
cnt = vio_ldq(&dev->sdev, dev->buf_list + 4096 - 8);
vio_stq(&dev->sdev, dev->buf_list + 4096 - 8, cnt + 1);
}
/**
* Get buffer descriptor from one of our receive buffer pools
*/
@ -206,7 +222,8 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
}
if (!dev->rx_bufs) {
return -1;
spapr_vlan_record_dropped_rx_frame(dev);
return 0;
}
if (dev->compat_flags & SPAPRVLAN_FLAG_RX_BUF_POOLS) {
@ -215,7 +232,8 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
bd = spapr_vlan_get_rx_bd_from_page(dev, size);
}
if (!bd) {
return -1;
spapr_vlan_record_dropped_rx_frame(dev);
return 0;
}
dev->rx_bufs--;
@ -266,6 +284,13 @@ static NetClientInfo net_spapr_vlan_info = {
.receive = spapr_vlan_receive,
};
static void spapr_vlan_flush_rx_queue(void *opaque)
{
VIOsPAPRVLANDevice *dev = opaque;
qemu_flush_queued_packets(qemu_get_queue(dev->nic));
}
static void spapr_vlan_reset_rx_pool(RxBufPool *rxp)
{
/*
@ -302,6 +327,9 @@ static void spapr_vlan_realize(VIOsPAPRDevice *sdev, Error **errp)
dev->nic = qemu_new_nic(&net_spapr_vlan_info, &dev->nicconf,
object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev);
qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a);
dev->rxp_timer = timer_new_us(QEMU_CLOCK_VIRTUAL, spapr_vlan_flush_rx_queue,
dev);
}
static void spapr_vlan_instance_init(Object *obj)
@ -332,6 +360,11 @@ static void spapr_vlan_instance_finalize(Object *obj)
dev->rx_pool[i] = NULL;
}
}
if (dev->rxp_timer) {
timer_del(dev->rxp_timer);
timer_free(dev->rxp_timer);
}
}
void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd)
@ -629,7 +662,13 @@ static target_ulong h_add_logical_lan_buffer(PowerPCCPU *cpu,
dev->rx_bufs++;
qemu_flush_queued_packets(qemu_get_queue(dev->nic));
/*
* Give guest some more time to add additional RX buffers before we
* flush the receive queue, so that e.g. fragmented IP packets can
* be passed to the guest in one go later (instead of passing single
* fragments if there is only one receive buffer available).
*/
timer_mod(dev->rxp_timer, qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + 500);
return H_SUCCESS;
}

View File

@ -1842,6 +1842,10 @@ static void ppc_spapr_init(MachineState *machine)
exit(1);
}
spapr->rtas_size = get_image_size(filename);
if (spapr->rtas_size < 0) {
error_report("Could not get size of LPAR rtas '%s'", filename);
exit(1);
}
spapr->rtas_blob = g_malloc(spapr->rtas_size);
if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) {
error_report("Could not load LPAR rtas '%s'", filename);
@ -2132,15 +2136,6 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr, uint64_t size,
int i, fdt_offset, fdt_size;
void *fdt;
/*
* Check for DRC connectors and send hotplug notification to the
* guest only in case of hotplugged memory. This allows cold plugged
* memory to be specified at boot time.
*/
if (!dev->hotplugged) {
return;
}
for (i = 0; i < nr_lmbs; i++) {
drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB,
addr/SPAPR_MEMORY_BLOCK_SIZE);
@ -2154,7 +2149,12 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr, uint64_t size,
drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp);
addr += SPAPR_MEMORY_BLOCK_SIZE;
}
spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs);
/* send hotplug notification to the
* guest only in case of hotplugged memory
*/
if (dev->hotplugged) {
spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs);
}
}
static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,

View File

@ -76,6 +76,37 @@ static IOMMUAccessFlags spapr_tce_iommu_access_flags(uint64_t tce)
}
}
static uint64_t *spapr_tce_alloc_table(uint32_t liobn,
uint32_t page_shift,
uint32_t nb_table,
int *fd,
bool need_vfio)
{
uint64_t *table = NULL;
uint64_t window_size = (uint64_t)nb_table << page_shift;
if (kvm_enabled() && !(window_size >> 32)) {
table = kvmppc_create_spapr_tce(liobn, window_size, fd, need_vfio);
}
if (!table) {
*fd = -1;
table = g_malloc0(nb_table * sizeof(uint64_t));
}
trace_spapr_iommu_new_table(liobn, table, *fd);
return table;
}
static void spapr_tce_free_table(uint64_t *table, int fd, uint32_t nb_table)
{
if (!kvm_enabled() ||
(kvmppc_remove_spapr_tce(table, fd, nb_table) != 0)) {
g_free(table);
}
}
/* Called from RCU critical section */
static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr,
bool is_write)
@ -142,21 +173,13 @@ static MemoryRegionIOMMUOps spapr_iommu_ops = {
static int spapr_tce_table_realize(DeviceState *dev)
{
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
uint64_t window_size = (uint64_t)tcet->nb_table << tcet->page_shift;
if (kvm_enabled() && !(window_size >> 32)) {
tcet->table = kvmppc_create_spapr_tce(tcet->liobn,
window_size,
&tcet->fd,
tcet->need_vfio);
}
if (!tcet->table) {
size_t table_size = tcet->nb_table * sizeof(uint64_t);
tcet->table = g_malloc0(table_size);
}
trace_spapr_iommu_new_table(tcet->liobn, tcet, tcet->table, tcet->fd);
tcet->fd = -1;
tcet->table = spapr_tce_alloc_table(tcet->liobn,
tcet->page_shift,
tcet->nb_table,
&tcet->fd,
tcet->need_vfio);
memory_region_init_iommu(&tcet->iommu, OBJECT(dev), &spapr_iommu_ops,
"iommu-spapr",
@ -242,11 +265,8 @@ static void spapr_tce_table_unrealize(DeviceState *dev, Error **errp)
QLIST_REMOVE(tcet, list);
if (!kvm_enabled() ||
(kvmppc_remove_spapr_tce(tcet->table, tcet->fd,
tcet->nb_table) != 0)) {
g_free(tcet->table);
}
spapr_tce_free_table(tcet->table, tcet->fd, tcet->nb_table);
tcet->fd = -1;
}
MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet)

View File

@ -1093,13 +1093,11 @@ static void spapr_phb_add_pci_device(sPAPRDRConnector *drc,
spapr_tce_set_need_vfio(tcet, true);
}
if (dev->hotplugged) {
fdt = create_device_tree(&fdt_size);
fdt_start_offset = spapr_create_pci_child_dt(phb, pdev, fdt, 0);
if (!fdt_start_offset) {
error_setg(errp, "Failed to create pci child device tree node");
goto out;
}
fdt = create_device_tree(&fdt_size);
fdt_start_offset = spapr_create_pci_child_dt(phb, pdev, fdt, 0);
if (!fdt_start_offset) {
error_setg(errp, "Failed to create pci child device tree node");
goto out;
}
drck->attach(drc, DEVICE(pdev),
@ -1816,7 +1814,7 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
_FDT(fdt_setprop(fdt, bus_off, "interrupt-map", &interrupt_map,
sizeof(interrupt_map)));
tcet = spapr_tce_find_by_liobn(SPAPR_PCI_LIOBN(phb->index, 0));
tcet = spapr_tce_find_by_liobn(phb->dma_liobn);
if (!tcet) {
return -1;
}

View File

@ -345,6 +345,8 @@ int kvm_arch_init(MachineState *ms, KVMState *s);
int kvm_arch_init_vcpu(CPUState *cpu);
bool kvm_vcpu_id_is_valid(int vcpu_id);
/* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
unsigned long kvm_arch_vcpu_id(CPUState *cpu);

View File

@ -1459,6 +1459,12 @@ static int kvm_max_vcpus(KVMState *s)
return (ret) ? ret : kvm_recommended_vcpus(s);
}
bool kvm_vcpu_id_is_valid(int vcpu_id)
{
KVMState *s = KVM_STATE(current_machine->accelerator);
return vcpu_id >= 0 && vcpu_id < kvm_max_vcpus(s);
}
static int kvm_init(MachineState *ms)
{
MachineClass *mc = MACHINE_GET_CLASS(ms);

View File

@ -163,7 +163,7 @@ static inline bool kvmppc_spapr_use_multitce(void)
static inline void *kvmppc_create_spapr_tce(uint32_t liobn,
uint32_t window_size, int *fd,
bool vfio_accel)
bool need_vfio)
{
return NULL;
}

View File

@ -284,8 +284,6 @@ void ppc_hash64_set_external_hpt(PowerPCCPU *cpu, void *hpt, int shift,
CPUPPCState *env = &cpu->env;
Error *local_err = NULL;
cpu_synchronize_state(CPU(cpu));
if (hpt) {
env->external_htab = hpt;
} else {

View File

@ -756,27 +756,20 @@ static void gen_cmpli(DisasContext *ctx)
/* isel (PowerPC 2.03 specification) */
static void gen_isel(DisasContext *ctx)
{
TCGLabel *l1, *l2;
uint32_t bi = rC(ctx->opcode);
uint32_t mask;
TCGv_i32 t0;
uint32_t mask = 0x08 >> (bi & 0x03);
TCGv t0 = tcg_temp_new();
TCGv zr;
l1 = gen_new_label();
l2 = gen_new_label();
tcg_gen_extu_i32_tl(t0, cpu_crf[bi >> 2]);
tcg_gen_andi_tl(t0, t0, mask);
mask = 0x08 >> (bi & 0x03);
t0 = tcg_temp_new_i32();
tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
if (rA(ctx->opcode) == 0)
tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
else
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
tcg_gen_br(l2);
gen_set_label(l1);
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
gen_set_label(l2);
tcg_temp_free_i32(t0);
zr = tcg_const_tl(0);
tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rD(ctx->opcode)], t0, zr,
rA(ctx->opcode) ? cpu_gpr[rA(ctx->opcode)] : zr,
cpu_gpr[rB(ctx->opcode)]);
tcg_temp_free(zr);
tcg_temp_free(t0);
}
/* cmpb: PowerPC 2.05 specification */
@ -1617,141 +1610,109 @@ static void gen_cntlzd(DisasContext *ctx)
/* rlwimi & rlwimi. */
static void gen_rlwimi(DisasContext *ctx)
{
uint32_t mb, me, sh;
TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
uint32_t sh = SH(ctx->opcode);
uint32_t mb = MB(ctx->opcode);
uint32_t me = ME(ctx->opcode);
mb = MB(ctx->opcode);
me = ME(ctx->opcode);
sh = SH(ctx->opcode);
if (likely(sh == (31-me) && mb <= me)) {
tcg_gen_deposit_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
cpu_gpr[rS(ctx->opcode)], sh, me - mb + 1);
if (sh == (31-me) && mb <= me) {
tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1);
} else {
target_ulong mask;
TCGv_i32 t0;
TCGv t1;
TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
tcg_gen_deposit_i64(t0, cpu_gpr[rS(ctx->opcode)],
cpu_gpr[rS(ctx->opcode)], 32, 32);
tcg_gen_rotli_i64(t0, t0, sh);
#else
tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
#endif
#if defined(TARGET_PPC64)
mb += 32;
me += 32;
#endif
mask = MASK(mb, me);
t0 = tcg_temp_new_i32();
t1 = tcg_temp_new();
tcg_gen_andi_tl(t0, t0, mask);
tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
tcg_temp_free(t0);
tcg_gen_trunc_tl_i32(t0, t_rs);
tcg_gen_rotli_i32(t0, t0, sh);
tcg_gen_extu_i32_tl(t1, t0);
tcg_temp_free_i32(t0);
tcg_gen_andi_tl(t1, t1, mask);
tcg_gen_andi_tl(t_ra, t_ra, ~mask);
tcg_gen_or_tl(t_ra, t_ra, t1);
tcg_temp_free(t1);
}
if (unlikely(Rc(ctx->opcode) != 0))
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, t_ra);
}
}
/* rlwinm & rlwinm. */
static void gen_rlwinm(DisasContext *ctx)
{
uint32_t mb, me, sh;
TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
uint32_t sh = SH(ctx->opcode);
uint32_t mb = MB(ctx->opcode);
uint32_t me = ME(ctx->opcode);
sh = SH(ctx->opcode);
mb = MB(ctx->opcode);
me = ME(ctx->opcode);
if (likely(mb == 0 && me == (31 - sh))) {
if (likely(sh == 0)) {
tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
} else {
TCGv t0 = tcg_temp_new();
tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
tcg_gen_shli_tl(t0, t0, sh);
tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
tcg_temp_free(t0);
}
} else if (likely(sh != 0 && me == 31 && sh == (32 - mb))) {
TCGv t0 = tcg_temp_new();
tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
tcg_gen_shri_tl(t0, t0, mb);
tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
tcg_temp_free(t0);
} else if (likely(mb == 0 && me == 31)) {
TCGv_i32 t0 = tcg_temp_new_i32();
tcg_gen_trunc_tl_i32(t0, cpu_gpr[rS(ctx->opcode)]);
tcg_gen_rotli_i32(t0, t0, sh);
tcg_gen_extu_i32_tl(cpu_gpr[rA(ctx->opcode)], t0);
tcg_temp_free_i32(t0);
if (mb == 0 && me == (31 - sh)) {
tcg_gen_shli_tl(t_ra, t_rs, sh);
tcg_gen_ext32u_tl(t_ra, t_ra);
} else if (sh != 0 && me == 31 && sh == (32 - mb)) {
tcg_gen_ext32u_tl(t_ra, t_rs);
tcg_gen_shri_tl(t_ra, t_ra, mb);
} else {
TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
tcg_gen_deposit_i64(t0, cpu_gpr[rS(ctx->opcode)],
cpu_gpr[rS(ctx->opcode)], 32, 32);
tcg_gen_rotli_i64(t0, t0, sh);
#else
tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
#endif
#if defined(TARGET_PPC64)
mb += 32;
me += 32;
#endif
tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
tcg_temp_free(t0);
if (sh == 0) {
tcg_gen_andi_tl(t_ra, t_rs, MASK(mb, me));
} else {
TCGv_i32 t0 = tcg_temp_new_i32();
tcg_gen_trunc_tl_i32(t0, t_rs);
tcg_gen_rotli_i32(t0, t0, sh);
tcg_gen_andi_i32(t0, t0, MASK(mb, me));
tcg_gen_extu_i32_tl(t_ra, t0);
tcg_temp_free_i32(t0);
}
}
if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, t_ra);
}
if (unlikely(Rc(ctx->opcode) != 0))
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
/* rlwnm & rlwnm. */
static void gen_rlwnm(DisasContext *ctx)
{
uint32_t mb, me;
mb = MB(ctx->opcode);
me = ME(ctx->opcode);
TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
TCGv t_rb = cpu_gpr[rB(ctx->opcode)];
uint32_t mb = MB(ctx->opcode);
uint32_t me = ME(ctx->opcode);
TCGv_i32 t0, t1;
if (likely(mb == 0 && me == 31)) {
TCGv_i32 t0, t1;
t0 = tcg_temp_new_i32();
t1 = tcg_temp_new_i32();
tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);
tcg_gen_trunc_tl_i32(t1, cpu_gpr[rS(ctx->opcode)]);
tcg_gen_andi_i32(t0, t0, 0x1f);
tcg_gen_rotl_i32(t1, t1, t0);
tcg_gen_extu_i32_tl(cpu_gpr[rA(ctx->opcode)], t1);
tcg_temp_free_i32(t0);
tcg_temp_free_i32(t1);
} else {
TCGv t0;
#if defined(TARGET_PPC64)
TCGv t1;
mb += 32;
me += 32;
#endif
t0 = tcg_temp_new();
tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1f);
#if defined(TARGET_PPC64)
t1 = tcg_temp_new_i64();
tcg_gen_deposit_i64(t1, cpu_gpr[rS(ctx->opcode)],
cpu_gpr[rS(ctx->opcode)], 32, 32);
tcg_gen_rotl_i64(t0, t1, t0);
tcg_temp_free_i64(t1);
#else
tcg_gen_rotl_i32(t0, cpu_gpr[rS(ctx->opcode)], t0);
#endif
if (unlikely(mb != 0 || me != 31)) {
#if defined(TARGET_PPC64)
mb += 32;
me += 32;
#endif
tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
} else {
tcg_gen_andi_tl(t0, t0, MASK(32, 63));
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
}
tcg_temp_free(t0);
t0 = tcg_temp_new_i32();
t1 = tcg_temp_new_i32();
tcg_gen_trunc_tl_i32(t0, t_rb);
tcg_gen_trunc_tl_i32(t1, t_rs);
tcg_gen_andi_i32(t0, t0, 0x1f);
tcg_gen_rotl_i32(t1, t1, t0);
tcg_temp_free_i32(t0);
tcg_gen_andi_i32(t1, t1, MASK(mb, me));
tcg_gen_extu_i32_tl(t_ra, t1);
tcg_temp_free_i32(t1);
if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, t_ra);
}
if (unlikely(Rc(ctx->opcode) != 0))
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
#if defined(TARGET_PPC64)
@ -1786,26 +1747,24 @@ static void glue(gen_, name##3)(DisasContext *ctx) \
gen_##name(ctx, 1, 1); \
}
static inline void gen_rldinm(DisasContext *ctx, uint32_t mb, uint32_t me,
uint32_t sh)
static void gen_rldinm(DisasContext *ctx, int mb, int me, int sh)
{
if (likely(sh != 0 && mb == 0 && me == (63 - sh))) {
tcg_gen_shli_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
} else if (likely(sh != 0 && me == 63 && sh == (64 - mb))) {
tcg_gen_shri_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], mb);
TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
if (sh != 0 && mb == 0 && me == (63 - sh)) {
tcg_gen_shli_tl(t_ra, t_rs, sh);
} else if (sh != 0 && me == 63 && sh == (64 - mb)) {
tcg_gen_shri_tl(t_ra, t_rs, mb);
} else {
TCGv t0 = tcg_temp_new();
tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
if (likely(mb == 0 && me == 63)) {
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
} else {
tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
}
tcg_temp_free(t0);
tcg_gen_rotli_tl(t_ra, t_rs, sh);
tcg_gen_andi_tl(t_ra, t_ra, MASK(mb, me));
}
if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, t_ra);
}
if (unlikely(Rc(ctx->opcode) != 0))
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
/* rldicl - rldicl. */
static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
{
@ -1816,6 +1775,7 @@ static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
gen_rldinm(ctx, mb, 63, sh);
}
GEN_PPC64_R4(rldicl, 0x1E, 0x00);
/* rldicr - rldicr. */
static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
{
@ -1826,6 +1786,7 @@ static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
gen_rldinm(ctx, 0, me, sh);
}
GEN_PPC64_R4(rldicr, 0x1E, 0x02);
/* rldic - rldic. */
static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
{
@ -1837,21 +1798,22 @@ static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
}
GEN_PPC64_R4(rldic, 0x1E, 0x04);
static inline void gen_rldnm(DisasContext *ctx, uint32_t mb, uint32_t me)
static void gen_rldnm(DisasContext *ctx, int mb, int me)
{
TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
TCGv t_rb = cpu_gpr[rB(ctx->opcode)];
TCGv t0;
t0 = tcg_temp_new();
tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
if (unlikely(mb != 0 || me != 63)) {
tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
} else {
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
}
tcg_gen_andi_tl(t0, t_rb, 0x3f);
tcg_gen_rotl_tl(t_ra, t_rs, t0);
tcg_temp_free(t0);
if (unlikely(Rc(ctx->opcode) != 0))
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
tcg_gen_andi_tl(t_ra, t_ra, MASK(mb, me));
if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, t_ra);
}
}
/* rldcl - rldcl. */
@ -1863,6 +1825,7 @@ static inline void gen_rldcl(DisasContext *ctx, int mbn)
gen_rldnm(ctx, mb, 63);
}
GEN_PPC64_R2(rldcl, 0x1E, 0x08);
/* rldcr - rldcr. */
static inline void gen_rldcr(DisasContext *ctx, int men)
{
@ -1872,32 +1835,31 @@ static inline void gen_rldcr(DisasContext *ctx, int men)
gen_rldnm(ctx, 0, me);
}
GEN_PPC64_R2(rldcr, 0x1E, 0x09);
/* rldimi - rldimi. */
static inline void gen_rldimi(DisasContext *ctx, int mbn, int shn)
static void gen_rldimi(DisasContext *ctx, int mbn, int shn)
{
uint32_t sh, mb, me;
TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
uint32_t sh = SH(ctx->opcode) | (shn << 5);
uint32_t mb = MB(ctx->opcode) | (mbn << 5);
uint32_t me = 63 - sh;
sh = SH(ctx->opcode) | (shn << 5);
mb = MB(ctx->opcode) | (mbn << 5);
me = 63 - sh;
if (unlikely(sh == 0 && mb == 0)) {
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
if (mb <= me) {
tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1);
} else {
TCGv t0, t1;
target_ulong mask;
target_ulong mask = MASK(mb, me);
TCGv t1 = tcg_temp_new();
t0 = tcg_temp_new();
tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
t1 = tcg_temp_new();
mask = MASK(mb, me);
tcg_gen_andi_tl(t0, t0, mask);
tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
tcg_temp_free(t0);
tcg_gen_rotli_tl(t1, t_rs, sh);
tcg_gen_andi_tl(t1, t1, mask);
tcg_gen_andi_tl(t_ra, t_ra, ~mask);
tcg_gen_or_tl(t_ra, t_ra, t1);
tcg_temp_free(t1);
}
if (unlikely(Rc(ctx->opcode) != 0))
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, t_ra);
}
}
GEN_PPC64_R4(rldimi, 0x1E, 0x06);
#endif

View File

@ -9231,6 +9231,14 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp)
#if !defined(CONFIG_USER_ONLY)
cpu->cpu_dt_id = (cs->cpu_index / smp_threads) * max_smt
+ (cs->cpu_index % smp_threads);
if (kvm_enabled() && !kvm_vcpu_id_is_valid(cpu->cpu_dt_id)) {
error_setg(errp, "Can't create CPU with id %d in KVM", cpu->cpu_dt_id);
error_append_hint(errp, "Adjust the number of cpus to %d "
"or try to raise the number of threads per core\n",
cpu->cpu_dt_id * smp_threads / max_smt);
return;
}
#endif
if (tcg_enabled()) {

View File

@ -1430,7 +1430,7 @@ spapr_iommu_pci_get(uint64_t liobn, uint64_t ioba, uint64_t ret, uint64_t tce) "
spapr_iommu_pci_indirect(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t iobaN, uint64_t tceN, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tcelist=0x%"PRIx64" iobaN=0x%"PRIx64" tceN=0x%"PRIx64" ret=%"PRId64
spapr_iommu_pci_stuff(uint64_t liobn, uint64_t ioba, uint64_t tce_value, uint64_t npages, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tcevalue=0x%"PRIx64" npages=%"PRId64" ret=%"PRId64
spapr_iommu_xlate(uint64_t liobn, uint64_t ioba, uint64_t tce, unsigned perm, unsigned pgsize) "liobn=%"PRIx64" 0x%"PRIx64" -> 0x%"PRIx64" perm=%u mask=%x"
spapr_iommu_new_table(uint64_t liobn, void *tcet, void *table, int fd) "liobn=%"PRIx64" tcet=%p table=%p fd=%d"
spapr_iommu_new_table(uint64_t liobn, void *table, int fd) "liobn=%"PRIx64" table=%p fd=%d"
# hw/ppc/ppc.c
ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "adjusted from 0x%"PRIx64" to 0x%"PRIx64", diff %"PRId64" (%"PRId64"s)"