Commit Graph

957 Commits

Author SHA1 Message Date
Andreas Färber
c05efcb18e cpu: Add CPUArchState pointer to CPUState
The target-specific ENV_GET_CPU() macros have allowed us to navigate
from CPUArchState to CPUState. The reverse direction was not supported.
Avoid introducing CPU_GET_ENV() macros by initializing an untyped
pointer that is initialized in derived instance_init functions.

The field may not be called "env" due to it being poisoned.

Acked-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2013-02-16 14:51:00 +01:00
Andreas Färber
60925d2644 target-ppc: Move TCG initialization to PowerPCCPU initfn
Ensures that a QOM-created PowerPCCPU is usable.

Signed-off-by: Andreas Färber <afaerber@suse.de>
2013-02-16 14:50:58 +01:00
Andreas Färber
4776ce6003 target-ppc: Update PowerPCCPU to QOM realizefn
Adapt ppc_cpu_realize() signature, hook it up to DeviceClass and set
realized = true in cpu_ppc_init().

Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2013-02-16 14:50:56 +01:00
Markus Armbruster
312fd5f290 error: Strip trailing '\n' from error string arguments (again)
Commit 6daf194d and be62a2eb got rid of a bunch, but they keep coming
back.  Tracked down with this Coccinelle semantic patch:

    @r@
	expression err, eno, cls, fmt;
	position p;
    @@
    (
	error_report(fmt, ...)@p
    |
	error_set(err, cls, fmt, ...)@p
    |
	error_set_errno(err, eno, cls, fmt, ...)@p
    |
	error_setg(err, fmt, ...)@p
    |
	error_setg_errno(err, eno, fmt, ...)@p
    )
    @script:python@
	fmt << r.fmt;
	p << r.p;
    @@
    if "\\n" in str(fmt):
	print "%s:%s:%s:%s" % (p[0].file, p[0].line, p[0].column, fmt)

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1360354939-10994-4-git-send-email-armbru@redhat.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-11 08:13:19 -06:00
Paolo Bonzini
5c099537a6 cpu: do not use object_delete
CPUs are never added to the composition tree, so delete is achieved
simply by removing the last references to them.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-01 15:53:11 -06:00
Andreas Färber
350ed2fcd9 target-ppc: Fix target_ulong vs. hwaddr format mismatches
Since HWADDR_PRIx is always the same now, use %016 for TARGET_PPC64 and
%08 for common code. This may slightly change the ppc64 debug output.

Signed-off-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-01 10:43:41 -06:00
Andreas Färber
476b6d1619 target-ppc: Fix build for PPC_DEBUG_DISAS
In r5949 / 76db3ba44e (target-ppc: memory
load/store rework) variable little_endian was replaced with ctx.le_mode.
Update the debug code.

Signed-off-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
2013-02-01 01:52:03 +01:00
Andreas Färber
cca48a93a9 target-ppc: Fix unused variable warning for FLUSH_ALL_TLBS
Signed-off-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
2013-02-01 01:52:02 +01:00
Alexander Graf
8e33944f8c PPC: Unify dcbzl code path
The bit that makes a dcbz instruction a dcbzl instruction was declared as
reserved in ppc32 ISAs. However, hardware simply ignores the bit, making
code valid if it simply invokes dcbzl instead of dcbz even on 750 and G4.

Thus, mark the bit as unreserved so that we properly emulate a simple dcbz
in case we're running on non-G5s.

While at it, also refactor the code to check the 970 special case during
runtime. This way we don't need to differenciate between a 970 dcbz and
any other dcbz anymore. We also allow for future improvements to add e500mc
dcbz handling.

Reported-by: Amadeusz Sławiński <amade@asmblr.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2013-02-01 01:52:02 +01:00
Andreas Färber
2b8c275499 cpu: Add model resolution support to CPUClass
Introduce CPUClass::class_by_name and add a default implementation.
Hook up the alpha and ppc implementations.

Introduce a wrapper function cpu_class_by_name().

Signed-off-by: Andreas Färber <afaerber@suse.de>
2013-01-27 14:52:04 +01:00
Eduardo Habkost
b164e48ed1 kvm: Create kvm_arch_vcpu_id() function
This will allow each architecture to define how the VCPU ID is set on
the KVM_CREATE_VCPU ioctl call.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Acked-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2013-01-27 14:34:26 +01:00
Mike Qiu
fe828a4d4b target-ppc: Give a meaningful error if too many threads are specified
Currently the target-ppc tcg code only supports a single thread.  You can
specify more, but they're treated identically to multiple cores.  On KVM
we obviously can't support more threads than the hardware; if more are
specified it will cause strange and cryptic errors.

This patch clarifies the situation by giving a simple meaningful error if
more threads are specified than we can support.

Signed-off-by: Mike Qiu <qiudayu@linux.vnet.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2013-01-25 22:02:55 +01:00
Alexander Graf
5b95b8b9c1 PPC: KVM: Add support for EPR with KVM
This patch links KVM EPR support to the existing TCG support we have now.

Signed-off-by: Alexander Graf <agraf@suse.de>
2013-01-18 19:06:57 +01:00
Alexander Graf
746a870b3c PPC: Provide zero SVR for -cpu e500mc and e5500
Even though our -cpu types for e500mc and e5500 are no real CPUs that
actually have version registers, a guest might still want to access
said version register and that has to succeed for a guest to be happy.

So let's expose a zero SVR value on E500_SVR SPR reads.

Signed-off-by: Alexander Graf <agraf@suse.de>
2013-01-18 19:06:57 +01:00
Andreas Färber
55e5c28502 cpu: Move cpu_index field to CPUState
Note that target-alpha accesses this field from TCG, now using a
negative offset. Therefore the field is placed last in CPUState.

Pass PowerPCCPU to [kvm]ppc_fixup_cpu() to facilitate this change.

Move common parts of mips cpu_state_reset() to mips_cpu_reset().

Acked-by: Richard Henderson <rth@twiddle.net> (for alpha)
[AF: Rebased onto ppc CPU subclasses and openpic changes]
Signed-off-by: Andreas Färber <afaerber@suse.de>
2013-01-15 04:09:13 +01:00
Andreas Färber
1b7ce68fb4 target-ppc: Error out for -cpu host on unknown PVR
Previously we silently exited, with subclasses we got an opcode warning.
Instead, explicitly tell the user what's wrong.

An indication for this is -cpu ? showing "host" with an all-zero PVR.

Signed-off-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
2013-01-07 17:37:11 +01:00
Andreas Färber
2985b86b5c target-ppc: Slim conversion of model definitions to QOM subclasses
Since the model list is highly macrofied, keep ppc_def_t for now and
save a pointer to it in PowerPCCPUClass. This results in a flat list of
subclasses including aliases, to be refined later.

Move cpu_ppc_init() to translate_init.c and drop helper.c.
Long-term the idea is to turn translate_init.c into a standalone cpu.c.

Inline cpu_ppc_usable() into type registration.

Split cpu_ppc_register() in two by code movement into the initfn and
by turning the remaining part into a realizefn.
Move qemu_init_vcpu() call into the new realizefn and adapt
create_ppc_opcodes() to return an Error.

Change ppc_find_by_pvr() -> ppc_cpu_class_by_pvr().
Change ppc_find_by_name() -> ppc_cpu_class_by_name().

Turn -cpu host into its own subclass. This requires to move the
kvm_enabled() check in ppc_cpu_class_by_name() to avoid the class being
found via the normal name lookup in the !kvm_enabled() case.
Turn kvmppc_host_cpu_def() into the class_init and add an initfn that
asserts KVM is in fact enabled.

Implement -cpu ? and the QMP equivalent in terms of subclasses.
This newly exposes -cpu host to the user, ordered last for -cpu ?.

Signed-off-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
2013-01-07 17:37:11 +01:00
Alexander Graf
68c2dd7006 PPC: Bring EPR support closer to reality
We already used to support the external proxy facility of FSL MPICs,
but only implemented it halfway correctly.

This patch adds support for

  * dynamic enablement of the EPR facility
  * interrupt acknowledgement only when the interrupt is delivered

This way the implementation now is closer to real hardware.

Signed-off-by: Alexander Graf <agraf@suse.de>
2013-01-07 17:37:11 +01:00
Stuart Yoder
1a61a9ae61 PPC: KVM: set has-idle in guest device tree
On e500mc, the platform doesn't provide a way for the CPU to go idle.

To still not uselessly burn CPU time, expose an idle hypercall to the guest
if kvm supports it.

Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>
[agraf: adjust for current code base, add patch description, fix non-kvm case]
Signed-off-by: Alexander Graf <agraf@suse.de>
2013-01-07 17:37:11 +01:00
Scott Wood
a1bb73849f ppc/booke: fix crit/mcheck/debug exceptions
Book E does not play games with certain bits of xSRR1 being MSR save
bits and others being error status.  xSRR1 is the old MSR, period.
This was causing things like MSR[CE] to be lost, even in the saved
version, as soon as you take an exception.

rfci/rfdi/rfmci are fixed to pass the actual xSRR1 register contents,
rather than the register number.

Put FIXME comments on the hack that is "asrr0/1".  The whole point of
separate exception levels is so that you can, for example, take a machine
check or debug interrupt without corrupting critical-level operations.
The right xSRR0/1 set needs to be chosen based on CPU type flags.

Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2013-01-07 17:37:10 +01:00
Andreas Färber
501a7ce727 Merge branch 'master' of git://git.qemu.org/qemu into qom-cpu
Adapt header include paths.

Signed-off-by: Andreas Färber <afaerber@suse.de>
2012-12-23 00:40:49 +01:00
Andreas Färber
a60f24b56b cpu: Move kvm_state field into CPUState
Adapt some functions to take CPUState / {PowerPC,S390}CPU argument.

Signed-off-by: Andreas Färber <afaerber@suse.de>
2012-12-19 14:09:32 +01:00
Andreas Färber
1bc22652d6 kvm: Pass CPUState to kvm_vcpu_ioctl()
Adapt helper functions to pass X86CPU / PowerPCCPU / S390CPU.

Signed-off-by: Andreas Färber <afaerber@suse.de>
2012-12-19 14:09:31 +01:00
Andreas Färber
20d695a925 kvm: Pass CPUState to kvm_arch_*
Move kvm_vcpu_dirty field into CPUState to simplify things and change
its type to bool while at it.

Signed-off-by: Andreas Färber <afaerber@suse.de>
2012-12-19 14:09:31 +01:00
Paolo Bonzini
6b4c305cbd fpu: move public header file to include/fpu
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2012-12-19 08:32:46 +01:00
Paolo Bonzini
9c17d615a6 softmmu: move include files to include/sysemu/
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2012-12-19 08:32:45 +01:00
Paolo Bonzini
1de7afc984 misc: move include files to include/qemu/
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2012-12-19 08:32:39 +01:00
Paolo Bonzini
14cccb6185 qom: move include files to include/qom/
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2012-12-19 08:31:32 +01:00
Paolo Bonzini
022c62cbbc exec: move include files to include/exec/
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2012-12-19 08:31:31 +01:00
Paolo Bonzini
76cad71136 build: kill libdis, move disassemblers to disas/
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2012-12-19 08:29:06 +01:00
Blue Swirl
a8a826a3c3 exec: refactor cpu_restore_state
Refactor common code around calls to cpu_restore_state().

tb_find_pc() has now no external users, make it static.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2012-12-16 08:35:24 +00:00
David Gibson
b162d02e94 target-ppc: Don't use hwaddr to represent hardware state
The hwaddr type is somewhat vaguely defined as being able to contain bus
addresses on the widest possible bus in the system.  For that reason it's
discouraged for representing specific pieces of persistent hardware state,
which should instead use an explicit width type that matches the bits
available in real hardware.  In particular, because of the possibility that
the size of hwaddr might change if different buses are added to the target
in future, it's not suitable for use in vm state descriptions for savevm
and migration.

This patch purges such unwise uses of hwaddr from the ppc target code,
which turns out to be just one.  The ppcemb_tlb_t struct, used on a number
of embedded ppc models to represent a TLB entry contains a hwaddr for the
real address field.  This patch changes it to be a fixed uint64_t which is
suitable enough for all machine types which use this structure.

Other uses of hwaddr in CPUPPCState turn out not to be problematic:
htab_base and htab_mask are just used for the convenience of the TCG code;
the underlying machine state is the SDR1 register, which is stored with
a suitable type already.  Likewise the mpic_cpu_base field is only used
internally and does not represent fundamental hardware state which needs to
be saved.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2012-12-14 13:12:57 +01:00
Evgeny Voevodin
ab1103def4 TCG: Use gen_opc_instr_start from context instead of global variable.
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2012-12-08 14:24:43 +00:00
Evgeny Voevodin
c9c99c22d5 TCG: Use gen_opc_icount from context instead of global variable.
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2012-12-08 14:24:42 +00:00
Evgeny Voevodin
25983cad31 TCG: Use gen_opc_pc from context instead of global variable.
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2012-12-08 14:24:42 +00:00
Julio Guerra
f0cc4aa845 PPC: Fix missing TRACE exception
This patch fixes bug 1031698 :
https://bugs.launchpad.net/qemu/+bug/1031698

If we look at the (truncated) translation of the conditional branch
instruction in the test submitted in the bug post, the call to the
exception helper is missing in the "bne-false" chunk of translated
code :

IN:
bne-    0x1800278

OUT:
0xb544236d:  jne    0xb5442396

0xb5442373:  mov    %ebp,(%esp)
0xb5442376:  mov    $0x44,%ebx
0xb544237b:  mov    %ebx,0x4(%esp)
0xb544237f:  mov    $0x1800278,%ebx
0xb5442384:  mov    %ebx,0x25c(%ebp)
0xb544238a:  call   0x827475a
                     ^^^^^^^^^^^^^^^^^^

0xb5442396:  mov    %ebp,(%esp)
0xb5442399:  mov    $0x44,%ebx
0xb544239e:  mov    %ebx,0x4(%esp)
0xb54423a2:  mov    $0x1800270,%ebx
0xb54423a7:  mov    %ebx,0x25c(%ebp)

Indeed, gen_exception(ctx, excp) called by gen_goto_tb (called by
gen_bcond) changes ctx->exception's value to excp's :

gen_bcond()
{
  gen_goto_tb(ctx, 0, ctx->nip + li - 4);
  /* ctx->exception value is POWERPC_EXCP_BRANCH */

  gen_goto_tb(ctx, 1, ctx->nip);
  /* ctx->exception now value is POWERPC_EXCP_TRACE */
}

Making the following gen_goto_tb()'s test false during the second call :

if ((ctx->singlestep_enabled &
    (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
    ctx->exception == POWERPC_EXCP_BRANCH /* false...*/) {
         target_ulong tmp = ctx->nip;
         ctx->nip = dest;
         /* ... and this is the missing call */
         gen_exception(ctx, POWERPC_EXCP_TRACE);
         ctx->nip = tmp;
}

So the patch simply adds the missing matching case, fixing our problem.

Signed-off-by: Julio Guerra <guerr@julio.in>
Signed-off-by: Alexander Graf <agraf@suse.de>
2012-11-26 19:53:26 +01:00
Evgeny Voevodin
92414b31e7 TCG: Use gen_opc_buf from context instead of global variable.
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2012-11-17 13:53:36 +00:00
Evgeny Voevodin
efd7f48600 TCG: Use gen_opc_ptr from context instead of global variable.
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2012-11-17 13:53:27 +00:00
Blue Swirl
f4359b9ffe disas: avoid using cpu_single_env
Pass around CPUArchState instead of using global cpu_single_env.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Acked-by: Richard Henderson <rth@twiddle.net>
Acked-by: Aurelien Jarno <aurelien@aurel32.net>
Acked-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
2012-11-10 13:49:20 +00:00
Blue Swirl
ef84755ebb Merge branch 'trivial-patches' of git://github.com/stefanha/qemu
* 'trivial-patches' of git://github.com/stefanha/qemu:
  pc: Drop redundant test for ROM memory region
  exec: make some functions static
  target-ppc: make some functions static
  ppc: add missing static
  vnc: add missing static
  vl.c: add missing static
  target-sparc: make do_unaligned_access static
  m68k: Return semihosting errno values correctly
  cadence_uart: More debug information

Conflicts:
	target-m68k/m68k-semi.c
2012-11-03 12:55:05 +00:00
Blue Swirl
6575c289f8 target-ppc: make some functions static
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Acked-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2012-11-01 19:49:45 +01:00
Blue Swirl
434482925e ppc: add missing static
Add missing 'static' qualifiers.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Acked-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2012-11-01 19:49:45 +01:00
Anthony Liguori
98c8a73b2e Merge remote-tracking branch 'afaerber/qom-cpu' into staging
* afaerber/qom-cpu: (35 commits)
  target-i386: Pass X86CPU to kvm_handle_halt()
  target-i386: Pass X86CPU to kvm_get_mp_state()
  cpu: Move thread_id to CPUState
  cpus: Pass CPUState to run_on_cpu()
  target-i386: Pass X86CPU to cpu_x86_inject_mce()
  target-i386: Pass X86CPU to kvm_mce_inject()
  cpus: Pass CPUState to [qemu_]cpu_has_work()
  spapr: Pass PowerPCCPU to hypercalls
  spapr: Pass PowerPCCPU to spapr_hypercall()
  target-ppc: Pass PowerPCCPU to cpu_ppc_hypercall
  target-ppc: Pass PowerPCCPU to powerpc_excp()
  xtensa_pic: Pass XtensaCPU to xtensa_ccompare_cb()
  cpus: Pass CPUState to qemu_wait_io_event_common()
  cpus: Pass CPUState to flush_queued_work()
  cpu: Move queued_work_{first,last} to CPUState
  cpus: Pass CPUState to qemu_cpu_kick()
  target-ppc: Rename kvm_kick_{env => cpu} and pass PowerPCCPU
  ppc: Pass PowerPCCPU to {ppc6xx,ppc970,power7,ppc40x,ppce500}_set_irq()
  cpus: Pass CPUState to qemu_tcg_init_vcpu()
  cpus: Pass CPUState to qemu_tcg_cpu_thread_fn
  ...

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-11-01 11:12:32 -05:00
David Gibson
3030442054 target-ppc: Extend FPU state for newer POWER CPUs
This patch adds some extra FPU state to CPUPPCState.  Specifically,
fpscr is extended to a target_ulong bits, since some recent (64 bit)
CPUs now have more status bits than fit inside 32 bits.  Also, we add
the 32 VSR registers present on CPUs with VSX (these extend the
standard FP regs, which together with the Altivec/VMX registers form a
64 x 128bit register file for VSX).

We don't actually support the instructions using these extra registers
in TCG yet, but we still need a place to store the state so we can
sync it with KVM and savevm/loadvm it.  This patch updates the savevm
code to not fail on the extended state, but also does not actually
save it - that's a project for another patch.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2012-11-01 13:02:22 +01:00
David Gibson
ac7d12ba25 target-ppc: Rework storage of VPA registration state
We change the storage of the VPA information to explicitly use fixed
size integer types which will make life easier for syncing this data with
KVM, which we will need in future.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
[agraf: fix commit message]
Signed-off-by: Alexander Graf <agraf@suse.de>
2012-11-01 13:02:22 +01:00
Andreas Färber
3993c6bddf cpus: Pass CPUState to [qemu_]cpu_has_work()
For target-mips also change the return type to bool.

Make include paths for cpu-qom.h consistent for alpha and unicore32.

Signed-off-by: Andreas Färber <afaerber@suse.de>
[AF: Updated new target-openrisc function accordingly]
Acked-by: Richard Henderson <rth@twiddle.net> (for alpha)
2012-10-31 04:11:37 +01:00
Andreas Färber
aa100fa4c9 spapr: Pass PowerPCCPU to spapr_hypercall()
Needed for changing the hypercall handlers' argument type to PowerPCCPU.

Signed-off-by: Andreas Färber <afaerber@suse.de>
2012-10-31 01:02:45 +01:00
Andreas Färber
1b14670a38 target-ppc: Pass PowerPCCPU to cpu_ppc_hypercall
Adapt emulate_spapr_hypercall() accordingly.

Needed for changing spapr_hypercall() argument type to PowerPCCPU.

Signed-off-by: Andreas Färber <afaerber@suse.de>
2012-10-31 01:02:45 +01:00
Andreas Färber
5c26a5b303 target-ppc: Pass PowerPCCPU to powerpc_excp()
Needed for changing cpu_ppc_hypercall() argument type to PowerPCCPU.

Signed-off-by: Andreas Färber <afaerber@suse.de>
2012-10-31 01:02:45 +01:00
Andreas Färber
c08d7424d6 cpus: Pass CPUState to qemu_cpu_kick()
CPUArchState is no longer needed there.

Signed-off-by: Andreas Färber <afaerber@suse.de>
2012-10-31 01:02:45 +01:00