diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index 34d0905..5cf56cc 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -116,10 +116,7 @@ function block_menu() {
   $items['admin/structure/block'] = array(
     'title' => 'Blocks',
     'description' => 'Configure what block content appears in your site\'s sidebars and other regions.',
-    'page callback' => 'block_admin_display',
-    'page arguments' => array($default_theme),
-    'access arguments' => array('administer blocks'),
-    'file' => 'block.admin.inc',
+    'route_name' => 'block_admin_display'
   );
   $items['admin/structure/block/add/%/%'] = array(
     'title' => 'Configure block',
@@ -159,11 +156,8 @@ function block_menu() {
       $theme = $themes[$key];
       $items['admin/structure/block/list/' . $plugin_id] = array(
         'title' => check_plain($theme->info['name']),
-        'page arguments' => array($key),
         'type' => $key == $default_theme ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
-        'access callback' => '_block_themes_access',
-        'access arguments' => array($key),
-        'file' => 'block.admin.inc',
+        'route_name' => 'block_admin_display.' . $plugin_id
       );
       $items['admin/structure/block/demo/' . $key] = array(
         'title' => check_plain($theme->info['name']),
diff --git a/core/modules/block/block.routing.yml b/core/modules/block/block.routing.yml
index af247b0..ccd5276 100644
--- a/core/modules/block/block.routing.yml
+++ b/core/modules/block/block.routing.yml
@@ -4,3 +4,11 @@ block_admin_block_delete:
     _form: '\Drupal\block\Form\AdminBlockDeleteForm'
   requirements:
     _permission: 'administer blocks'
+
+block_admin_display:
+  pattern: '/admin/structure/block'
+  defaults:
+    _controller: '\Drupal\block\Controller\BlockListController::listing'
+    entity_type: 'block'
+  requirements:
+    _permission: 'administer blocks'
diff --git a/core/modules/block/block.services.yml b/core/modules/block/block.services.yml
index 745bf66..24e5ff1 100644
--- a/core/modules/block/block.services.yml
+++ b/core/modules/block/block.services.yml
@@ -9,3 +9,12 @@ services:
     factory_method: get
     factory_service: cache_factory
     arguments: [block]
+  block.route_subscriber:
+    class: Drupal\block\Routing\RouteSubscriber
+    tags:
+      - { name: event_subscriber}
+    arguments: ['@service_container']
+  block.theme_access_check:
+    class: Drupal\block\Access\BlockThemeAccessCheck
+    tags:
+      - { name: access_check}
diff --git a/core/modules/block/lib/Drupal/block/Access/BlockThemeAccessCheck.php b/core/modules/block/lib/Drupal/block/Access/BlockThemeAccessCheck.php
new file mode 100644
index 0000000..4612396
--- /dev/null
+++ b/core/modules/block/lib/Drupal/block/Access/BlockThemeAccessCheck.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\block\Access\BlockThemeAccessCheck.
+ */
+
+namespace Drupal\block\Access;
+
+use Drupal\Core\Access\AccessCheckInterface;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Checks access for displaying block page.
+ */
+class BlockThemeAccessCheck implements AccessCheckInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function applies(Route $route) {
+    return array_key_exists('_block_themes_access', $route->getRequirements());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access(Route $route, Request $request) {
+    $theme = $request->attributes->get('theme');
+    return user_access('administer blocks') && drupal_theme_access($theme);
+  }
+
+}
diff --git a/core/modules/block/lib/Drupal/block/Controller/BlockListController.php b/core/modules/block/lib/Drupal/block/Controller/BlockListController.php
new file mode 100644
index 0000000..5081ea5
--- /dev/null
+++ b/core/modules/block/lib/Drupal/block/Controller/BlockListController.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\block\Controller\BlockListController.
+ */
+
+namespace Drupal\block\Controller;
+
+use Drupal\Core\Entity\Controller\EntityListController;
+
+/**
+ * Defines a controller to list blocks.
+ */
+class BlockListController extends EntityListController{
+
+  /**
+   * Shows the block administration page.
+   *
+   * @param string $entity_type
+   * @param string|null $theme
+   *
+   * @return array|string
+   *   A render array as expected by drupal_render().
+   */
+  public function listing($entity_type, $theme = NULL) {
+    $default_theme = $theme ?: config('system.theme')->get('default');
+    return $this->entityManager->getListController($entity_type)->render($default_theme);
+  }
+
+}
diff --git a/core/modules/block/lib/Drupal/block/Routing/RouteSubscriber.php b/core/modules/block/lib/Drupal/block/Routing/RouteSubscriber.php
new file mode 100644
index 0000000..f847c1c
--- /dev/null
+++ b/core/modules/block/lib/Drupal/block/Routing/RouteSubscriber.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\block\Routing\RouteSubscriber.
+ */
+
+namespace Drupal\block\Routing;
+
+use Drupal\Core\Routing\RouteBuildEvent;
+use Drupal\Core\Routing\RoutingEvents;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\Routing\Route;
+use Drupal\system\Plugin\Type\PluginUIManager;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Listens to the dynamic route events.
+ */
+class RouteSubscriber implements EventSubscriberInterface {
+
+  /**
+   * The injection container that should be passed into the controller factory.
+   *
+   * @var \Symfony\Component\DependencyInjection\ContainerInterface
+   */
+  protected $container;
+
+
+  /**
+   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
+   *   The service container this object should use.
+   */
+  public function __construct(ContainerInterface $container) {
+    $this->container = $container;
+  }
+  /**
+   * Implements EventSubscriberInterface::getSubscribedEvents().
+   */
+  static function getSubscribedEvents() {
+    $events[RoutingEvents::DYNAMIC] = 'routes';
+    return $events;
+  }
+
+  /**
+   * Generate dynamic routes for various block pages.
+   *
+   * @param \Drupal\Core\Routing\RouteBuildEvent $event
+   *   The route building event.
+   *
+   * @return \Symfony\Component\Routing\RouteCollection
+   *   The route collection that contains the new dynamic route.
+   */
+  public function routes(RouteBuildEvent $event) {
+    $collection = $event->getRouteCollection();
+    foreach ($this->container->get('plugin.manager.system.plugin_ui')->getDefinitions() as $plugin_id => $plugin) {
+      list($plugin_base, $key) = explode(':', $plugin_id);
+      if ($plugin_base == 'block_plugin_ui') {
+        $route = new Route('admin/structure/block/list/' . $plugin_id, array(
+          '_controller' => '\Drupal\block\Controller\BlockListController::listing',
+          'entity_type' => 'block',
+          'theme' => $key,
+        ),array(
+          '_block_themes_access' => 'TRUE',
+        ));
+        $collection->add('block_admin_display.' . $plugin_id , $route);
+      }
+    }
+  }
+}
